31

Размер массива можно задавать по-разному, например, где-то определённой
константой или динамически, тогда в том модуле, где он определяется, его
размер всегда будет известен.

Всё равно не понимаю, зачем создавать лишние сущности.
Объект уже есть в памяти и работать с ним проще именно как с участком памяти,
а не через дополнительную надстройку, да ещё в виде файла.
И я не вижу никаких сложностей в использовании указателей, уж куда проще.

Это может быть длинная подпрограмма, что-то рассчитывающая или обрабатывающая,
без ветвлений, но с большим количеством переменных. Она  и будет выполняться
последовательно. Тут автор может только рационально распределить использование
переменных, у меня такая тенденция есть.

Пётр.

Пётр.

32 (31.01.2015 11:33:13 отредактировано )

Peter пишет:

llen: len=sizeof(struct sockaddr_in);if(len==0)goto llen; fin=fopen("imit_cam_cyc.in","r");if(fin!=NULL){n=fscanf(fin,"%hu%[^\n]",&uvp, buf); n=fscanf(fin,"%u%[^\n]",&usc,buf); n=fscanf(fin,"%d%[^\n]",&ncyc,buf); n=fscanf(fin,"%s%[^\n]",buf,buf+20); fclose(fin);} else{strcpy(buf,"127.0.0.1");ncyc=0;}usi.us=0;b=true;usc*=1000;

эпично.

вот, причесал:

http://pastebin.com/gKw1V5Q9

Peter пишет:

Размер массива можно задавать по-разному

нельзя. Размер массива это всегда константа.
(хотя в последнем стандарте разрешили новую фичу, динамические массивы на стеке).

Peter пишет:

Всё равно не понимаю, зачем создавать лишние сущности.

вы про что? Про функции? Это не лишние сущности.

Peter пишет:

Объект уже есть в памяти и работать с ним проще именно как с участком памяти,
а не через дополнительную надстройку, да ещё в виде файла.

ага. А как вы будете гарантировать консистентность памяти, когда два потока туда что-то одновременно пишут? Да даже если пишет всего один поток, а остальные читают, всё равно есть очень большая вероятность ошибки. Ну каноничный пример: переменная с временем в часах и минутах, программа сначала обновляет минуты…

ВНЕЗАПНО: другой поток это читает, и хотя сейчас 16:00, другой поток читает 15:00, т.к. минуты уже обновили, а часы не успели. Необходим какой-нить механизм для запрета чтения. В ФС такой механизм имеется, поток открывший файл со временем ВСЕГДА будет читать правильную информацию (15:59), даже когда другой процесс пишет в этот файл. Не, если вам нравится наворачивать свои костыли — пожалуйста, никто не против.

Peter пишет:

Тут автор может только рационально распределить использование
переменных, у меня такая тенденция есть.

нету. Я видел ваш код.

Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

33 (31.01.2015 14:40:11 отредактировано Peter)

Да могли бы не причёсывать, там же есть вариант с отступами. И я уже говорил,
что это не рабочая программа, это наскоро сделанный инструмент.

Насчёт размера массива не понял возражения. В любом случае там, где он определён,
его размер известен.

Лишняя сущность - это файл для доступа к участку памяти.
А синхронизация потоков - тоже не проблема, для этого есть средства.
Да, поток, открывший файл, прочитает то, что в нём на момент открытия,
даже если содержимое файла будет изменено другим потоком или программой,
а как потом учесть эти изменения? только закрыть и заново открыть,
или есть другие средства?

Пётр.

Пётр.

34

Peter пишет:

Да могли бы не причёсывать, там же есть вариант с отступами.

сделайте diff

Peter пишет:

И я уже говорил,
что это не рабочая программа, это наскоро сделанный инструмент.

не важно.

Peter пишет:

Насчёт размера массива не понял возражения. В любом случае там, где он определён,
его размер известен.

кому?

Peter пишет:

Лишняя сущность - это файл для доступа к участку памяти.

Peter пишет:

А синхронизация потоков - тоже не проблема, для этого есть средства.

ну вот вопрос: кто будет определять какие средства?

Peter пишет:

даже если содержимое файла будет изменено другим потоком или программой,
а как потом учесть эти изменения? только закрыть и заново открыть,
или есть другие средства?

вопрос в том, правильно, или НЕПРАВИЛЬНО прочитался файл или память?

Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

35

Хорошо, пусть не важно, но я не профессиональный программист,
так что, как я уже говорил, я не ограничиваю себя в коде.

Размер массива известен автору программы, кому же ещё.

Автор программы и будет определять, какие средства для него удобнее.
В случае с файлом самое простое - открыть и сразу же закрыть после
минования в нём надобности.

Вы же сами сказали, что файл всегда прочитается правильно.

А можете ответить на вопрос поста - почему в Ubuntu вызов gettimeofday()
влияет на то, что происходит до него, а в Debian нет?
Если эта моя ошибка, то в чём?

Пётр.

Пётр.

36 (31.01.2015 18:03:15 отредактировано )

Peter, э... т.е. вы согласны быть быдлокодером, да? Т.е. для вас допустимо писать быдлокод, потому что «я не ограничиваю себя в коде», так?

"размер массива" конечно известен автору, а если автор решил его поменять?

Peter пишет:

Вы же сами сказали, что файл всегда прочитается правильно.

нет, я такого не говорил. Читайте внимательнее.


Peter пишет:

А можете ответить на вопрос поста - почему в Ubuntu вызов gettimeofday()

Peter пишет:

влияет на то, что происходит до него, а в Debian нет?
Если эта моя ошибка, то в чём?

укажите точное место в коде.

да, если вам западло набрать man  gettimeofday
я наберу:

GETTIMEOFDAY(2)                                    Linux Programmer's Manual                                    GETTIMEOFDAY(2)

NAME
       gettimeofday, settimeofday - get / set time

SYNOPSIS
       #include <sys/time.h>

       int gettimeofday(struct timeval *tv, struct timezone *tz);

       int settimeofday(const struct timeval *tv, const struct timezone *tz);

   Feature Test Macro Requirements for glibc (see feature_test_macros(7)):

       settimeofday(): _BSD_SOURCE

DESCRIPTION
       The  functions  gettimeofday()  and settimeofday() can get and set the time as well as a timezone.  The tv argument is a
       struct timeval (as specified in <sys/time.h>):

           struct timeval {
               time_t      tv_sec;     /* seconds */
               suseconds_t tv_usec;    /* microseconds */
           };

       and gives the number of seconds and microseconds since the Epoch (see time(2)).  The tz argument is a struct timezone:

           struct timezone {
               int tz_minuteswest;     /* minutes west of Greenwich */
               int tz_dsttime;         /* type of DST correction */
           };

       If either tv or tz is NULL, the corresponding structure is not set or returned.   (However,  compilation  warnings  will
       result if tv is NULL.)

       The use of the timezone structure is obsolete; the tz argument should normally be specified as NULL.  (See NOTES below.)

       Under Linux there are some peculiar "warp clock" semantics associated with the settimeofday() system call if on the very
       first call (after booting) that has a non-NULL tz argument, the tv argument is NULL  and  the  tz_minuteswest  field  is
       nonzero.   (The  tz_dsttime field should be zero for this case.)  In such a case it is assumed that the CMOS clock is on
       local time, and that it has to be incremented by this amount to get UTC system time.  No doubt it is a bad idea  to  use
       this feature.

RETURN VALUE
       gettimeofday() and settimeofday() return 0 for success, or -1 for failure (in which case errno is set appropriately).

ERRORS
       EFAULT One of tv or tz pointed outside the accessible address space.

       EINVAL Timezone (or something else) is invalid.

       EPERM  The calling process has insufficient privilege to call settimeofday(); under Linux the CAP_SYS_TIME capability is
              required.

CONFORMING TO
       SVr4, 4.3BSD.  POSIX.1-2001 describes gettimeofday() but not settimeofday().  POSIX.1-2008 marks gettimeofday() as obso‐
       lete, recommending the use of clock_gettime(2) instead.

NOTES
       The  time returned by gettimeofday() is affected by discontinuous jumps in the system time (e.g., if the system adminis‐
       trator manually changes the system time).  If you need a monotonically increasing clock, see clock_gettime(2).

       Macros for operating on timeval structures are described in timeradd(3).

       Traditionally, the fields of struct timeval were of type long.

       The tz_dsttime field has never been used under Linux.  Thus, the following is purely of historic interest.

       On old systems, the field tz_dsttime contains a symbolic constant (values are given below) that indicates in which  part
       of  the  year Daylight Saving Time is in force.  (Note: this value is constant throughout the year: it does not indicate
       that DST is in force, it just selects an algorithm.)  The daylight saving time algorithms defined are as follows:

           DST_NONE     /* not on DST */
           DST_USA      /* USA style DST */
           DST_AUST     /* Australian style DST */
           DST_WET      /* Western European DST */
           DST_MET      /* Middle European DST */
           DST_EET      /* Eastern European DST */
           DST_CAN      /* Canada */
           DST_GB       /* Great Britain and Eire */
           DST_RUM      /* Romania */
           DST_TUR      /* Turkey */
           DST_AUSTALT  /* Australian style with shift in 1986 */

       Of course it turned out that the period in which Daylight Saving Time is in force cannot be given by a simple algorithm,
       one per country; indeed, this period is determined by unpredictable political decisions.  So this method of representing
       timezones has been abandoned.

SEE ALSO
       date(1), adjtimex(2), clock_gettime(2), time(2), ctime(3), ftime(3), timeradd(3), capabilities(7), time(7)

COLOPHON
       This page is part of release 3.69 of the Linux man-pages project.  A  description  of  the  project,  information  about
       reporting bugs, and the latest version of this page, can be found at http://www.kernel.org/doc/man-pages/.

Linux                                                      2012-04-26                                           GETTIMEOFDAY(2)
Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

37

drBatty пишет:

Peter, э... т.е. вы согласны быть быдлокодером, да? Т.е. для вас допустимо писать быдлокод, потому что «я не ограничиваю себя в коде», так?

В принципе да, так, хотя сознательно я всё же этого не делаю.

"размер массива" конечно известен автору, а если автор решил его поменять?

Если размер задан через аргумент или через константу, определённую в #define,
или через глобальную переменную, то никаких проблем, лишь бы везде использовалось
не число, а символьное обозначение.

Peter пишет:

Вы же сами сказали, что файл всегда прочитается правильно.

нет, я такого не говорил. Читайте внимательнее.

Хорошо, но то, что вы сказали, я недавно наблюдал при экспериментальной проверке того,
что происходит, когда одна программа читает файл, а другая в него пишет.

Peter пишет:

А можете ответить на вопрос поста - почему в Ubuntu вызов gettimeofday()

Peter пишет:

влияет на то, что происходит до него, а в Debian нет?
Если эта моя ошибка, то в чём?

укажите точное место в коде.

Он там встречается дважды внутри while(1), перед циклом по i от 0 до nr и после него.
Но, кажется, я в 1-м посте сказал, что то же самое происходит, если для эксперимента
поместить его до while(1).

Пётр.

Пётр.

38

Peter пишет:

Если размер задан через аргумент или через константу, определённую в #define,
или через глобальную переменную, то никаких проблем, лишь бы везде использовалось
не число, а символьное обозначение.

ну в обычной сишке "через число" нельзя, только через константу.

Peter пишет:

Хорошо, но то, что вы сказали, я недавно наблюдал при экспериментальной проверке того,
что происходит, когда одна программа читает файл, а другая в него пишет.

значит неправильно вы читали/писали.

Peter пишет:

Он там встречается дважды внутри while(1), перед циклом по i от 0 до nr и после него.
Но, кажется, я в 1-м посте сказал, что то же самое происходит, если для эксперимента
поместить его до while(1).

вот покажите код
ДО и ПОСЛЕ.
А я его попытаюсь собрать.
Только исправьте те недостатки, которые я перечислил здесь: http://pastebin.com/gKw1V5Q9

Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

39

Опять не понял, ДО и ПОСЛЕ чего?

Пётр.

Пётр.

40 (31.01.2015 20:35:21 отредактировано Peter)

Вот слегка поправленный вариант. Мои ответы помечены //!!!
http://pastebin.com/Tx1ZZSk3
Я имел в виду, что поместить gettimeofday() перед while(1), а внутри его закомментировать.

Пётр.

Пётр.

41

Peter пишет:

Вот слегка поправленный вариант. Мои ответы помечены //!!!

!!!совершенно мне не нужно ни то, ни другое

если бы вы сделали серелизацию и инициализацию отдельно, код был-бы намного короче, проще читаем, и его было-бы легко поддерживать.

Я ведь сказал в посте, что у меня есть своя bool.h

это называется ВНЕЗАПНО.
см. https://ru.wikipedia.org/wiki/%D0%9F%D1 … 0%B8%D1%8F
но русская вика, как обычно, очень однобоко трактует, правильнее

The principle of least astonishment (POLA) applies to user interface and software design, from the ergonomics standpoint.[1] It is alternatively referred to as the law or rule of least astonishment, or of least surprise.[2][3] "If a necessary feature has a high astonishment factor, it may be necessary to redesign the feature."

(выделение моё, источник https://en.wikipedia.org/wiki/Principle … tonishment )

memset для установки, bzero для обнуления

обнуление == установка в 0.

//!!! в "man bzero" сказано "void *", я и привожу, чтобы не было сообщений

а их и не будет в рамках ansi C. Потому что в void* в сишке можно кастовать что угодно без явного каста. Потому и в bzero такой тип, хотя по смыслу там char* должно быть.

так полагается, судя по man.

ладно, тут да, придётся, это проблема сишки.

я-то знаю, что это за длина. Это длина ожидаемой и принимаемой посылок.

дык назвали её как-нить более очевидно.

так удобнее запускать, т.к. не надо перенаправлять вывод.

угу. В итоге программа получается гвоздями прибита к одному файлу, и никак это не изменить.

в программе на Qt я иногда для целей отладки использую такую функцию:
//void prn_t (const char *buf, int n){

зачем вы не используете Qstring в программе на Qt?

можно и с break, но он подобен goto и его использование ухудшает логическую структуру,

breake НЕ нарушает структуру, потому что break не может перепрыгнуть не пойми куда, а лишь только на выход из цикла. Ну и когда я вижу while(1), то мне вполне очевидно, что там внутри break есть. А когда вижу while(b), то полагаю, что b это какая-то переменная, которая для продолжения цикла должна иметь истинное значение(не нулевое точнее). А потом ВНЕЗАПНО оказывается, что где-то перед этим b стало true, а где-то внутри цикла ещё более ВНЕЗАПНО стало нулём(а почему же не false?). Goto конечно плохо, но в данном случае оно не настолько ВНЕЗАПНОе, как это ваше b.

for(b=true; b;)
//!!! никогда не использую таких конструкций

а зря, ибо тут отлично видно, что b вначале стало true, а потом мы продолжаем цикл, пока b не станет false. Вполне очевидно, что это "стало false" закопано где-то в теле цикла, как оно есть на самом деле.
Тут сразу видно следующее:
1. всегда в начале цикла, на первой итерации b==true, т.ч. первая итерация выполняется всегда
2. переменная логическая, т.к. true.
3. выход из цикла где-то внутри задаётся, когда и b становится false.
И всё это вполне очевидно, когда видишь лишь одну строчку кода.

// for (i = 0; i < nr; i++, usi.us++)
//!!! не люблю таких конструкций. Пусть каждый занимается своим делом -
//!!! цикл наращивает переменную, а вычисления пусть будут внутри.
//!!! хотя компилятор так и сделает, но это выглядит как-то неестественно.

дык usi.us++ это тоже "наращивание переменной". Вы тут сразу две переменные наращиваете, т.ч. их и можно сразу нарастить.
И да, компилятор скорее всего будет наращивать только i, т.к. посчитать usi.us+i ему проще

                            for (i = 0; i < nr; i++)
                            {
                                    n = read(nfd, bufr, 1024);
                                    bufr[2] = usi.ch[1];
                                    bufr[3] = usi.ch[0];
                                    n = sendto(nfds, bufr, 1024, MSG_DONTROUTE,
                                       (struct sockaddr *) &addrvs, len);
                                    if (n < 0)
                                    {
                                            strcpy(buf, strerror(errno));
                                            fprintf(fout, "sendto: %d %d %s\n", i, errno, buf);
                                            fflush(fout);
                                            return 0;
                                    }
                                    usi.us++;
                            }

точнее

usi.us += nr;

usi.us внутри цикла не юзается, а цикл выполняется nr раз.

эта скобка от while(1), чтобы цикл выполнялся бесконечно.

можно было сразу такой комментарий поставить.

зачем же, если в него постоянно идёт запись?

а если ошибка? Вы, почему-то, делаете fflush(3) при ошибке, а не close(3).

Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

42 (01.02.2015 06:19:04 отредактировано )

Peter пишет:

Я имел в виду, что поместить gettimeofday() перед while(1), а внутри его закомментировать.

ну во первых: что вернула gettimeofday?
во вторых: что-то вы где-то напутали, и где-то вы испортили стек (локальные переменные). Мне что-то не распарсить ваши nfds, которые и вам-то наверное уже непонятны.

Было-бы лучше, если-бы вы выделяли malloc'ом память для своих структур, так их проще контролировать. Т.е. прямо в том месте, где они вам нужны.

Эта ваше len вообще не нужно и вредно. Лучше прямо так и пишите:

                                    n = sendto(nfds, bufr, 1024, MSG_DONTROUTE,
                                       (struct sockaddr *) &addrvs, sizeof(addrvs));

а то я вангую, что как раз len у вас и портится, что приводит к сбою sendto.

кстати там (const struct sockaddr*).

drBatty пишет:

(struct sockaddr *) &addrvs, sizeof(addrvs)

а может надо sizeof(struct sockaddr) ?
если честно, я и не помню, размер какой структуры указывать, они могут иметь разный размер в разных системах. Может проблема как раз в этом, вы указали неверный размер, и внутрь sendto поехал мусор, например структура tv, в которой у вас время пишется. Ну вот sedto и не поняла такую подставу.

Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

43 (01.02.2015 09:35:32 отредактировано Peter)

drBatty пишет:
Peter пишет:

Вот слегка поправленный вариант. Мои ответы помечены //!!!

!!!совершенно мне не нужно ни то, ни другое

если бы вы сделали серелизацию и инициализацию отдельно, код был-бы намного короче, проще читаем, и его было-бы легко поддерживать.

Мне проще именно так.

memset для установки, bzero для обнуления

обнуление == установка в 0.

Да, но удобнее с bzero().

я-то знаю, что это за длина. Это длина ожидаемой и принимаемой посылок.

дык назвали её как-нить более очевидно.

lencp - CONTROL_PACKET length, в этой программе h-файл с его определением не подключается.

так удобнее запускать, т.к. не надо перенаправлять вывод.

угу. В итоге программа получается гвоздями прибита к одному файлу, и никак это не изменить.

в программе на Qt я иногда для целей отладки использую такую функцию:
//void prn_t (const char *buf, int n){

зачем вы не используете Qstring в программе на Qt?

Так это же программа, а не подпрограмма, в ней это значения не имеет.
Я и в программе на Qt делаю так же, т.е. вывожу отладочную информацию в FILE *p_out.
Так удобнее.

можно и с break, но он подобен goto и его использование ухудшает логическую структуру,

breake НЕ нарушает структуру, потому что break не может перепрыгнуть не пойми куда, а лишь только на выход из цикла. Ну и когда я вижу while(1), то мне вполне очевидно, что там внутри break есть. А когда вижу while(b), то полагаю, что b это какая-то переменная, которая для продолжения цикла должна иметь истинное значение(не нулевое точнее). А потом ВНЕЗАПНО оказывается, что где-то перед этим b стало true, а где-то внутри цикла ещё более ВНЕЗАПНО стало нулём(а почему же не false?). Goto конечно плохо, но в данном случае оно не настолько ВНЕЗАПНОе, как это ваше b.

b не внезапное и его использование не нарушает порядка исполнения, в отличие от break,
и выглядит как-то приятнее.

for(b=true; b;)
//!!! никогда не использую таких конструкций

а зря, ибо тут отлично видно, что b вначале стало true, а потом мы продолжаем цикл, пока b не станет false. Вполне очевидно, что это "стало false" закопано где-то в теле цикла, как оно есть на самом деле.
Тут сразу видно следующее:
1. всегда в начале цикла, на первой итерации b==true, т.ч. первая итерация выполняется всегда
2. переменная логическая, т.к. true.
3. выход из цикла где-то внутри задаётся, когда и b становится false.
И всё это вполне очевидно, когда видишь лишь одну строчку кода.

Всё же это использование for не по назначению, а логичнее для этого while(b).

// for (i = 0; i < nr; i++, usi.us++)
//!!! не люблю таких конструкций. Пусть каждый занимается своим делом -
//!!! цикл наращивает переменную, а вычисления пусть будут внутри.
//!!! хотя компилятор так и сделает, но это выглядит как-то неестественно.

дык usi.us++ это тоже "наращивание переменной". Вы тут сразу две переменные наращиваете, т.ч. их и можно сразу нарастить.
И да, компилятор скорее всего будет наращивать только i, т.к. посчитать usi.us+i ему проще

                            for (i = 0; i < nr; i++)
                            {
                                    n = read(nfd, bufr, 1024);
                                    bufr[2] = usi.ch[1];
                                    bufr[3] = usi.ch[0];
                                    n = sendto(nfds, bufr, 1024, MSG_DONTROUTE,
                                       (struct sockaddr *) &addrvs, len);
                                    if (n < 0)
                                    {
                                            strcpy(buf, strerror(errno));
                                            fprintf(fout, "sendto: %d %d %s\n", i, errno, buf);
                                            fflush(fout);
                                            return 0;
                                    }
                                    usi.us++;
                            }

точнее

usi.us += nr;

usi.us внутри цикла не юзается, а цикл выполняется nr раз.

Используется, посмотрите немного выше.

эта скобка от while(1), чтобы цикл выполнялся бесконечно.

можно было сразу такой комментарий поставить.

зачем же, если в него постоянно идёт запись?

а если ошибка? Вы, почему-то, делаете fflush(3) при ошибке, а не close(3).

Там в файл выводится сообщение, вызванное реакцией системы и установкой errno,
т.е. это не ошибка для программы. А вообще при окончании программы система сама
закроет незакрытые файлы.

Пётр.

drBatty пишет:
Peter пишет:

Я имел в виду, что поместить gettimeofday() перед while(1), а внутри его закомментировать.

ну во первых: что вернула gettimeofday?
во вторых: что-то вы где-то напутали, и где-то вы испортили стек (локальные переменные). Мне что-то не распарсить ваши nfds, которые и вам-то наверное уже непонятны.

Было-бы лучше, если-бы вы выделяли malloc'ом память для своих структур, так их проще контролировать. Т.е. прямо в том месте, где они вам нужны.

Эта ваше len вообще не нужно и вредно. Лучше прямо так и пишите:

                                    n = sendto(nfds, bufr, 1024, MSG_DONTROUTE,
                                       (struct sockaddr *) &addrvs, sizeof(addrvs));

а то я вангую, что как раз len у вас и портится, что приводит к сбою sendto.

кстати там (const struct sockaddr*).

drBatty пишет:

(struct sockaddr *) &addrvs, sizeof(addrvs)

а может надо sizeof(struct sockaddr) ?
если честно, я и не помню, размер какой структуры указывать, они могут иметь разный размер в разных системах. Может проблема как раз в этом, вы указали неверный размер, и внутрь sendto поехал мусор, например структура tv, в которой у вас время пишется. Ну вот sedto и не поняла такую подставу.

nfds - это просто file descriptor, там же есть проверка, что он правильный.
Я не замечал, что в случае ошибки в sendto() возврашает gettimeofday(),
мне была важно, чтобы работала sendto().
Я не вижу надобности в таком простом случае использовать malloc(). Ведь в h-файле есть описание
структуры, вот компилятор и выделит ей памяти, сколько надо.
Размер структуры ведь не меняется, поэтому удобнее использовать переменную
с её значением, это короче.
Всё может быть, но ведь gettimeofday() вызывается позже sendto(),
не знаю, как она могла повлиять.

Пётр.

Пётр.

44

Peter пишет:

Мне проще именно так.

вам не проще. Просто вы боитесь, что компилятор не осилит inline, и вы потеряете драгоценные такты на call/ret.

Peter пишет:

Да, но удобнее с bzero().

ну например для меня это несколько неожиданно. Кстати, в примерах юзают таки memset(3).

Peter пишет:

lencp - CONTROL_PACKET length

я про «n» говорил. Которая у вас сначала как exit status работает, а потом как какая-то длинна.

Peter пишет:

Так это же программа, а не подпрограмма, в ней это значения не имеет.
Я и в программе на Qt делаю так же, т.е. вывожу отладочную информацию в FILE *p_out.
Так удобнее.

нужна линяя сущность — размер буфера. Я так подозреваю, что именно в этом у вас ошибка. Лишние сущности вредны как раз тем, что с ними можно ошибиться. Почему я и говорил о

sizeof(array)/sizeof(array[0])

тут длинна массива — лишняя сущность, и её нужно избегать (как в этом коде — путём вычисления. Но вычисление будет только во время компиляции, потому бесплатно в рантайме).

Peter пишет:

b не внезапное и его использование не нарушает порядка исполнения, в отличие от break,
и выглядит как-то приятнее.

ну мне-то со стороны виднее, что в вашем коде ВНЕЗАПНО. А вот вам это изнутри незаметно.

Peter пишет:

Всё же это использование for не по нзаначению, а логичнее для этого while(b).

дык откуда вы взяли "назначение for"? Из паскаля/фортрана? Ну может там и другое назначение, я уж и не помню. В C/C++ это просто способ сделать заголовок, условие, и переход к след. итерации внутри одной строки, а не разбросанным по коду в 10и местах.
Вовсе не обязательно, что нужно именно for(i=0; i<10; i++), это самый простой пример, и не более того.

Peter пишет:

Используется, посмотрите немного выше.

дык это ВНЕ цикла, зачем в цикле nr раз прибавлять 1, если ВНУТРИ цикла эта CENSORED не используется? Только путаете читателя(прежде всего себя).

Peter пишет:

Там в файл выводится сообщение, вызванное реакцией системы и установкой errno,
т.е. это не ошибка для программы. А вообще при окончании программы система сама
закроет незакрытые файлы.

зачем тогда fflush(3)? Вы уж определитесь.

Peter пишет:

nfds - это просто file descriptor, там же есть проверка, что он правильный.

я видел. Но по названию это понять невозможно. Необходимо manual читать.

Peter пишет:

Я не замечал, что в случае ошибки в sendto() возврашает gettimeofday(),
мне была важно, чтобы работала sendto().

дык у вас все переменные в одной "куче" (в стеке, не в heap'е), потому, если какая-то функция что-то не то пишет, то она будет затирать совершенно неожиданные переменные(т.к. невозможно предсказать, в каком порядке расставит переменные компилятор), проблема также в том, что у вас переменные имеют очень большое время жизни, т.е. их нельзя в регистр засунуть. А память — вещь ненадёжная, учитывая ваш стиль написания кода(лишние касты например или переменные, которые вообще не нужны, как например len).

Peter пишет:

Я не вижу в таком простом случае использовать malloc(). Ведь в h-файле есть описание
структуры, вот компилятор и выделит ей памяти, сколько надо.

да, вот только вы потом пишете в эту структуру не "сколько надо", а некое len байтов. Причём у вас написано

len = sizeof(struct sockaddr_in);

а вы используете ВНЕЗАПНО

n = sendto(nfdc, bufr, lencp, MSG_DONTROUTE,
                           (struct sockaddr *) &addrcc, len);

с чего вы взяли, что разные структуры имеют одинаковую длину? Не, может и имеют конечно, а может и нет. Я не знаю.

В примере написано вот как:

           struct sockaddr_storage peer_addr;
           socklen_t peer_addr_len;
…
               peer_addr_len = sizeof(struct sockaddr_storage);
               nread = recvfrom(sfd, buf, BUF_SIZE, 0,
                       (struct sockaddr *) &peer_addr, &peer_addr_len);

т.е. во первых у них структура другая,  struct sockaddr_storage
во вторых они посылают размер этой структуры, но "вычисляют" его непосредственно перед использованием(и пофиг, что в цикле). В третьих название у них нормальное, а не как у вас, len. Это надо весь код шерстить, что-бы проверить, юзается-ли len где-то ещё?

Peter пишет:

Всё может быть, но ведь gettimeofday() вызывается позже sendto(),
не знаю, как она могла повлиять.

это потому, что в ваших макаронах даже вам ничерта непонятно. Любуйтесь на свой код:

                        gettimeofday(&tv1, NULL);
                        for (i = 0; i < nr; i++)
                        {
                                n = read(nfd, bufr, 1024);
                                bufr[2] = usi.ch[1];
                                bufr[3] = usi.ch[0];
                                n = sendto(nfds, bufr, 1024, MSG_DONTROUTE,
                                   (struct sockaddr *) &addrvs, len);
                                if (n < 0)
                                {
                                        strcpy(buf, strerror(errno));
                                        fprintf(fout, "sendto: %d %d %s\n", i, errno, buf);
                                        fflush(fout);
                                        // abort(3) опять забыли
                                }
                                usi.us++;// это нужно было в заголовке цикла сделать:
                                // for (i = 0; i < nr; i++, usi.us++)
                        }
                        close(nfd);
                        gettimeofday(&tv2, NULL);
Peter пишет:

gettimeofday() вызывается позже

какая из двух?

Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

45

У меня кусок с вводом через FILE *fin певреносится из программы в другую
и я нахожу такой вариант удобным. Об inline и не думал, это не такая операция,
на которой надо экономить. Это разовая операция.

И буфер всегда отвожу для вывода и достаточно большой,
никакой проблемы в этом нет.

Так не одновременно же n используется в разных смыслах.
И вообще чем меньше переменных, тем лучше.

Мне как-то неприятно вычислять длину массива через sizeof().
У меня она обычно известно или из константы или через аргумент
в подпрограмме, как и некоторые библиотечные подпрограммы предусматривают.
На этом много не выиграешь.

Обнуление b не более и не менее внезапно, чем break,
но при этом не изменяет порядка выполнения.

Всё же основное назначение for - организация цикла по индексу,
а по условию логичнее изпользовать while(b) или метку с goto.
И usi внутри цикла исползуется, посмотрите внимательнее.

fflush() для надёжности, т.к. без него, если после fprintf() произойдёт крах программы,
то вывод в файл не попадёт.

sendto() в моём случае ничего не затирает, во всяком случае, я на это надеюсь,
она только заканчивается с ошибкой и устанавливает errno.

sendto() вызывается правильно, в соответствии с man и примерами.
Адрес приводится к чему надо, а длина указывается самой структуры.
Размер её никак не может меняться в ходе исполнения, так что всё равно,
когда его вычислять. Совершенно неважно, какую длину имеет sockaddr,
это приведение адреса осталось по историческим причинам и это забота
компилятора, а не моя.

Любoй вызов gettimeofday() влияет и я уже говорил, что он влияет самим
фактом своего наличия. Например, если в цикле его закомментировать и
поместить перед while(). Влияет в Ubuntu.

Пётр.

Пётр.

46

Peter пишет:

У меня кусок с вводом через FILE *fin певреносится из программы в другую
и я нахожу такой вариант удобным.

функцию напишите, типа my_error().

Peter пишет:

И буфер всегда отвожу для вывода и достаточно большой,
никакой проблемы в этом нет.

в данном случае вы размер задаёте в len, причём с точностью до char'а.

Peter пишет:

Так не одновременно же n используется в разных смыслах.
И вообще чем меньше переменных, тем лучше.

вы немного подзабыли правило: чем меньше переменных в одной и той же области действия, тем лучше.
т.е. в вашем случае надо было просто объявить

{
  int n;
  // использования этой n
}
{
  int n;
  // а это уже ДРУГАЯ n
}

у вас все переменные тащутся через огромный код, в котором ни одной функции нет.

Peter пишет:

Мне как-то неприятно вычислять длину массива через sizeof().

хм. А менять в трёх местах одно и то же число "приятно"?

Peter пишет:

или из константы

не наблюдаю в вашем коде ни одного слова const.

Peter пишет:

как и некоторые библиотечные подпрограммы предусматривают.

ну иногда иначе попросту не сделать. Это же сишка.

Peter пишет:

На этом много не выиграешь.

как вы не понимаете: речь не о выигрыше, речь о понятности кода.

Peter пишет:

Обнуление b не более и не менее внезапно, чем break,
но при этом не изменяет порядка выполнения.

изменяет, но в совершенно другом месте кода. Ну и потом непонятно, на кой ляд было определять false, а потом писать ноль? Кстати в C++ тип bool введён совершенно из других побуждений, для перезагрузки операторов. Без него компилятор не врубается, какую именно перезагрузку применять. В сишке перезагрузки нет, и потому смысл в true/false мне непонятен. Это как раз источник ошибок, ибо одно true не равно другому true, если на самом деле это int. Ну и время тратится на перевод разных true в 1, как положено по стандарту(к счастью в i80386+ придумали ещё одну Over9000'ю команду для этого. Точнее десяток двадцать восемь команд, setnz, setnge, и далее по списку).

Peter пишет:

Всё же основное назначение for - организация цикла по индексу,

откуда такие сведения?

Peter пишет:

а по условию логичнее изпользовать while(b) или метку с goto.

откуда? И да, про do{}while(); слышали?

Peter пишет:

И usi внутри цикла исползуется, посмотрите внимательнее.

не вижу. Именно usi.us НЕ используется, используется usi.ch.

Peter пишет:

fflush() для надёжности, т.к. без него, если после fprintf() произойдёт крах программы,
то вывод в файл не попадёт.

у вас там return обычно стоит, да ещё и return 0. Т.е. это у вас "нормальное завершение".
кстати close() оно ещё надёжнее будет.

Peter пишет:

sendto() в моём случае ничего не затирает, во всяком случае, я на это надеюсь,
она только заканчивается с ошибкой и устанавливает errno.

ох... sendto не затирает, затирает что-то ПЕРЕД sendto. Ну либо размер ошибочный, и sendto получает мусор вместе/вместо аргументов.

Peter пишет:

sendto() вызывается правильно, в соответствии с man и примерами.
Адрес приводится к чему надо, а длина указывается самой структуры.
Размер её никак не может меняться в ходе исполнения, так что всё равно,
когда его вычислять. Совершенно неважно, какую длину имеет sockaddr,
это приведение адреса осталось по историческим причинам и это забота
компилятора, а не моя.

ну если адрес никогда не меняется, то советую вам его объявить const, а лучше вычислять прямо в процессе.

Кроме того, у вас ошибка в типах: тип того, что выдаёт sizeof() является size_t, это uint64_t для amd64, и uint32_t для AI-32. А у вас это вообще int, в котором в обоих архитектурах 31 значащий бит (т.е. ошибка будет в обоих архитектурах). Если-бы вы прямо в функции писали-бы sizeof, ошибки бы и быть не могло(потому что на самом деле в sendto(3) тип socklen_t, в который гарантированно влезает size_t из любой архитектуры поддержывающихся glibc). Т.ч. как минимум вам следует определить

const socklen_t len = sizeof(…);

видимо тут размер задаётся как раз потому, что тип структуры может быть другим, это типа такое костыльное "наследование" из C++.

Peter пишет:

Совершенно неважно, какую длину имеет sockaddr,
это приведение адреса осталось по историческим причинам и это забота
компилятора, а не моя.

Увы, вы заблуждаетесь. Функция sendto отлично знает размер sockaddr, и раз она требует размер, то очевидно, что у структуры sockaddr_in есть "хвост". Проверьте сами, распечатав размер и той и другой структуры. Только учтите, что в разных системах оно может быть по разному.

Peter пишет:

Любoй вызов gettimeofday() влияет и я уже говорил, что он влияет самим
фактом своего наличия. Например, если в цикле его закомментировать и
поместить перед while(). Влияет в Ubuntu.

ну значит эта функция у вас пишет мусор куда-то не туда. Телепатирую, что ubuntu у вас 64х битная, а деб 32х битный, вот и получается, что в убунте мусора больше, и он влияет на sendto.

Ну а вообще такие вещи вообще просто обязаны вылезать, с вашим code style.

Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

47

Буфер я имел в виду для промежуточных целей, например, для использования в sprintf().

Я именно имел в виду кличество переменных в одном месте. И я всегда все определения
помещаю до исполнимых операторов, и в C++ тоже.

Если вы имеете в виду использование для разных целей n, то да, приятно.

const я пишу только тогда, когда компилятор без этого собщает об ошибке,
мне просто лень делать то, чего можно не делать.

Это у меня сложилось такое впечатление, что for - для организации цикла по индексу,
т.к. для других целей есть другие операторы.
Насчёт do{}  while{} слышал, но сам эту конструкцию не применяю,
разве только если случится её откуда-нибудь скопировать.

Ещё раз посмотрите внимательнее, что используется usi.us,
только вы этого не замечаете. Посмотрите, что такое usi.

Если сработал fflush(), то close() при return не обязателен.
Нормальное завершение - это выход без краха.

Вот в этом и проблема, что gettimeofday() портит то, что находится до её вызова.
По-видимому, в Ubuntu происходит нарушение причинно-следственных связей.

Поскольку в len хранимая в ней величина занимает несколько младших разрядов,
то ошибки с передачей int вместо size_t как аргумента не происходит, всё равно
аргумент передаётся по значению. Его можно задать и числом, компилятор
всё равно обработает аргумент правильно, ему же известно объявление функции.

Насчёт socklen_t посмотрите man, там сказано что-то вроде того,
что он оставлен для совместимости.

Так я знаю, что sockaddr и sockaddr_in имеют или могут иметь разную длину,
но в примерах использования sendto() передаётся размер именно sockaddr_in.
Это естественно, что указывается размер передаваемого объекта,
а дальше уже работа компилятора.

Обе системы 64-разрядные.

Пётр.

Пётр.

48

drBatty пишет:
Peter пишет:

Размер массива и так известен автору программы, зачем  к нему применять sizeof()?

очевидно для того, что-бы писать код, который не зависит от размера массива.

Ваш диалог мучает мозг.

Может быть на форуме стоило бы завести новый раздел?

49

stranger пишет:

Может быть на форуме стоило бы завести новый раздел?

Какой и зачем???
...Возможно тему перенести в Программирование , ну, как-бы, да...
...А раздел то зачем???

- Пап, а вирусы под линукс есть?
- Есть, но всего 5, и их сначала нужно откомпилировать под свою систему, дать права на запуск и запустить.
Как сделать и разместить скриншот || Прежде чем создавать тему

50

diablopc, Вы несомненно правы! Простите за невнимательность!

51 (02.02.2015 07:58:00 отредактировано )

Peter пишет:

я всегда все определения
помещаю до исполнимых операторов

с какой целью? Что-бы лазать по коду вверх/вниз, и искать "какой тип имеет len? int? OH SHI~~"

Peter пишет:

мне просто лень делать то, чего можно не делать.

если не писать const, то программа может будет работать, а может и нет. Зависит от положения Нептуна в тригоне воды. Что вы и наблюдаете.

Peter пишет:

Это у меня сложилось такое впечатление, что for - для организации цикла по индексу,
т.к. для других целей есть другие операторы.
Насчёт do{}  while{} слышал, но сам эту конструкцию не применяю,
разве только если случится её откуда-нибудь скопировать.

1. ваше впечатление неправильное.
2. вы применяйте, это лучше, чем goto.

Peter пишет:

Ещё раз посмотрите внимательнее, что используется usi.us,
только вы этого не замечаете. Посмотрите, что такое usi.

сразу бы сказали, что это union. Вы надомной издеваетесь, да? Написали что-то  непонятное, что работает в зависимости от фазы луны, и хотите что-бы все поняли?

Peter пишет:

Если сработал fflush(), то close() при return не обязателен.

если сработал fclose, то fflush не обязателен. Но fclose "надёжнее" fflush, и вы всё равно ничего писать в файл не будете, ибо return

Peter пишет:

Нормальное завершение - это выход без краха.

нормальное завершение — выход без ошибки.

Peter пишет:

Вот в этом и проблема, что gettimeofday() портит то, что находится до её вызова.
По-видимому, в Ubuntu происходит нарушение причинно-следственных связей.

не валите с больной головы на здоровую. Вы делите на ноль, и удивляетесь разному результату.

Peter пишет:

Поскольку в len хранимая в ней величина занимает несколько младших разрядов,
то ошибки с передачей int вместо size_t как аргумента не происходит, всё равно
аргумент передаётся по значению. Его можно задать и числом, компилятор
всё равно обработает аргумент правильно, ему же известно объявление функции.

вот и задавайте, а не плачьте "у меня в бубунте не работает, А-А-А!". Как задавать я уже рассказал:

sizeof(struct sockaddr_in)

сложно что-ли подставить и проверить? У вас жеж не работает, а не у меня!

Peter пишет:

Насчёт socklen_t посмотрите man, там сказано что-то вроде того,
что он оставлен для совместимости.

для тех, кто в танке:

Кроме того, у вас ошибка в типах: тип того, что выдаёт sizeof() является size_t, это uint64_t для amd64, и uint32_t для AI-32. А у вас это вообще int, в котором в обоих архитектурах 31 значащий бит (т.е. ошибка будет в обоих архитектурах). Если-бы вы прямо в функции писали-бы sizeof, ошибки бы и быть не могло(потому что на самом деле в sendto(3) тип socklen_t, в который гарантированно влезает size_t из любой архитектуры поддерживающихся glibc).

Peter пишет:

Так я знаю, что sockaddr и sockaddr_in имеют или могут иметь разную длину,
но в примерах использования sendto() передаётся размер именно sockaddr_in.

про какой именно пример вы говорите?

Peter пишет:

Это естественно, что указывается размер передаваемого объекта,

вообще-то нет. Вы передаёте объект в 100 байт, и пишите "длинна объекта 123 байта". Это не совсем "естественно".

Ещё раз, не нужно со мной спорить, если не верите, то проверяйте мои слова. Это так сложно, да?

Я не могу проверить за вас, да и вам наверное не интересно, как оно в Slackware Linux.


Peter пишет:

но в примерах использования sendto() передаётся размер именно sockaddr_in

а тип — напротив, sockaddr. Если вы не знали, то тип объекта тоже передаётся в функцию, а значит и размер (размер массива к сожалению теряется, ибо при передаче массива он преобразуется в указатель, что ВНЕЗАПНО не одно и то же. Но для структуры это не так).

Peter пишет:

а дальше уже работа компилятора.

в данном случае вы ему упрощаете работу:
1. тип аргумента &addrcc компилятор и без вас знает, но вы явно указали другой тип: (struct sockaddr *)
2. размер addrcc компилятор тоже знает. Но вы передаёте ещё и размер. И это оправданно, т.к. при сборке функции компилятор "знает" что аргумент sockaddr, но вы то подсовываете sockaddr_in!

stranger пишет:

Ваш диалог мучает мозг. Может быть на форуме стоило бы завести новый раздел?

Ткните на кнопку "жалоба" в первом посте. Я думал, мы давно в "программировании", извините, не хотел травмировать ваш МУГ  bk

Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

52

Благодарю за внимание, но, как мне кажется, вы уходите от ответа на первоначалаьно заданный вопрос.
Кроме того, не все ваши аргументы для меня убедительны.

Конечно, бывают случаи, когда использование do{} while{} обязательно, но вроде бы это в h-файлах,
а в программе можно и проще.

Когда нужен const, то компилятор об этом скажет. Например, он оказался необходим в функции prn_t().

Так мне не нужен каждый раз fclose(), я и пишу fflush().

Для меня нормальное завершение - это окончание программы по её желанию, а не вследствие краха.

И вот я не согласен с тем, как, по-вашему, надо передавать длину структуры. То вы советуете использовать переменную  типа size_t,
то sizeof(), которая, по вашим же словам, вообще константа. Никогда ещё не было проблем с передачей длины через переменную int.
Я думаю, что компилятор умеет обрабатывать все эти варианты. И я  уже  говорил, что приведение адреса к адресу sockaddr
требуется согласно man, так что ошибки я не вижу.

Каккой пример с sendto() - сейчас не могу сказать, какие-то встречались то ли в man'ах, то ли в книге. В книге точно через int.

Я передаю стуктуру и указываю её же размер, опять же так и в примерах её использования.  Я не встречал требования её
во что-то оборачивать, чтобы размер этого объекта был равен размеру sockaddr, хотя, возможно, это может требоваться.
Везде передаётся размер передаваемой структуры.

Так почему наличие gettimeofday() в тексте программы в Ubuntu влияет на работу sendto, а в Debian нет?

Пётр.

Пётр.

53

Peter, вы бы посмотрели отладчиком, что в вашей программе творится до криминальных вызовов, что после. А то местные болтуны вас совсем от темы увели...

54 (02.02.2015 14:34:23 отредактировано )

Peter пишет:

но, как мне кажется, вы уходите от ответа на первоначалаьно заданный вопрос.

я на него уже ответил:

drBatty пишет:

вангую, что вы как-то не правильно делаете, и добились UB.

анализ вашего кода это доказывает.
перечислять, что вы делаете неправильно, можно очень долго, даже в этом не сложном случае.

Peter пишет:

Кроме того, не все ваши аргументы для меня убедительны.

отлично вас понимаю, я сам раньше так(плохо) писал.

Peter пишет:

Конечно, бывают случаи, когда использование do{} while{} обязательно

не бывает. Необходимо и достаточно только if/goto, или while (без goto, как в brainfuck'е). Но зачем так себя ненавидеть?

Peter пишет:

но вроде бы это в h-файлах

это вы путаете с жутким и не нужным костылём для подпорки другого костыля.

Peter пишет:

Когда нужен const, то компилятор об этом скажет.

не скажет, увы. Для совместимости со старым кодом в сишке _можно_ не использовать const. Это если ваш код и так работает где угодно, а вас зовут "профессор Дональд Кнут", и вы умеете писать настолько крутые программы, которые работают на шестибитовых(или 36и битовых, причём сразу, без изменения кода и препроцессора) char'ах и int'ах любого размера.

Но вас зовут Пётр, а не Дональд Кнут. И ваш код не работает даже в убунте. Смиритесь.

Peter пишет:

Например, он оказался необходим в функции prn_t().

из неконстанты всегда можно сделать константу, обратное невозможно. sendto хочет константу, но очевидно, вы можете ей и неконстанту подсунуть. Она сделает из неконстанты константу и не будет её трогать. Откуда вывод: этот аргумент портится внутри вашего кода, а не внутри sendto из убунты, т.к. sendto принимает константу. Т.е. это ВЫ функцию мусором кормите.

Peter пишет:

Для меня нормальное завершение - это окончание программы по её желанию, а не вследствие краха.

т.е. если программа не смогла файл открыть, то это "её желание", да?

Peter пишет:

И вот я не согласен с тем, как, по-вашему, надо передавать длину структуры. То вы советуете использовать переменную  типа size_t,
то sizeof(), которая, по вашим же словам, вообще константа.

ох… Как же с вами тяжело-то! sizeof() это константа в рантайме, имеющая тип size_t. Но во время компиляции sizeof() эта переменная, т.к. мы не знаем, какой будет sizeof в той системе, где наш код будут собирать. В частности, мы не знаем sizeof(size_t).

Peter пишет:

Никогда ещё не было проблем с передачей длины через переменную int.

УЖЕ есть. Если-бы у вас не было проблем, у вас-бы всё работало.

Peter пишет:

Я думаю, что компилятор умеет обрабатывать все эти варианты. И я  уже  говорил, что приведение адреса к адресу sockaddr
требуется согласно man, так что ошибки я не вижу.

это приведение — кривой костыль. Для реализации в сишке полиморфизма, сходите по ссылке, и почитайте: https://ru.wikipedia.org/wiki/%D0%9F%D0 … A%D0%B0%29
Увы, в сишке нет полиморфизма, потому приходится такие вот нелепые, не очевидные, и ненадёжные хаки юзать. Даже в C++ с этим не очень хорошо(в c++11 вроде стало нормально, во всяком случае с т.з. практика).

Компилятор не умеет такое обрабатывать, и потому полагается на программиста, который ручками укажет точные размеры и точные типы. А компилятор эти вещи тупо передаст в функцию, как сказано, без проверок. Ну нет в сишке таой хорошей и кошерной штуки, как https://ru.wikipedia.org/wiki/Dynamic_cast Нужно всё вручную делать, причём очень внимательно, особенно, если функцию написали не вы сами.

Peter пишет:

Каккой пример с sendto() - сейчас не могу сказать, какие-то встречались то ли в man'ах, то ли в книге. В книге точно через int.

Сколько лет назад написана эта книга? 30 лет? 40? Ваш int конечно скастуется без предупреждений, но сделано это лишь для совместимости со старым кодом.

Peter пишет:

Я передаю стуктуру и указываю её же размер, опять же так и в примерах её использования.  Я не встречал требования её
во что-то оборачивать, чтобы размер этого объекта был равен размеру sockaddr, хотя, возможно, это может требоваться.
Везде передаётся размер передаваемой структуры.

так вас не смущает, что вы передаёте одну структуру, указывая размер другой?

Вас вообще передача размера не смущает? Почему функция сама не может посчитать размер того, что ей передали? Это же не какой-то буфер, для которого вы передаёте только указатель на начало, это структура, и функция прекрасно знает, как эта структура устроена!

Зачем вы в какую-то магию верите?

Peter пишет:

Так почему наличие gettimeofday() в тексте программы в Ubuntu влияет на работу sendto, а в Debian нет?

потому-что у вас что-то портится, если есть gettimeofday(). А в Debian у вас тоже наверное что-то портится, но на работу программы это не сказывается. Я же вам показывал код

804837e:   66 90                   xchg   ax,ax; NOP. Команда для выравнивания адреса. Цикл по адресу кратному 16 быстрее работает

помните? Что будет, если заменить эти байты на что угодно другое? Ничего не изменится. Т.ч. программа при UB вовсе не обязана зависнуть или ещё что-то не то сделать. Программа вполне может работать так, как вам этого хочется. Особенно в сишке. Потому-то сишку так ненавидят пионеры и школьники.

s.xbatob пишет:

вы бы посмотрели отладчиком

зачем сразу "отладчиком", можно и objdump. Можно и здесь выложить то, что у Петра получается.

s.xbatob пишет:

А то местные болтуны

мне что, Ubuntu устанавливать?

Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

55

drBatty пишет:
s.xbatob пишет:

вы бы посмотрели отладчиком

зачем сразу "отладчиком", можно и objdump. Можно и здесь выложить то, что у Петра получается.

s.xbatob пишет:

А то местные болтуны

мне что, Ubuntu устанавливать?

Если хотите поковыряться в чужом и не слишком аккуратном коде - попробуйте.  ag Я - не хочу. Но по-прежнему ставлю на то, что бага в коде программы, а вовсе не в системе.
Только вопрос изначально был о конкретной баге, приводящей к краху. А обсуждение съехало на светские разговоры о стиле программирования.

56

s.xbatob пишет:

Peter, вы бы посмотрели отладчиком, что в вашей программе творится до криминальных вызовов, что после. А то местные болтуны вас совсем от темы увели...

В ближайшие дни не получится, но совет хорош и попробую, если будет возможность.

Пётр.

Пётр.

57

Недавно где-то спрашивали, зачем эта конструкция, кажется, в fido7.ru.linux
и ему объяснили. Она действительно была нужна, но не знаю, можни ли было
там заменить её if/else. врод бы трбовалось именно do..while.

А что, Ubuntu настолько дружественный дистрибутив или там gcc особенно снисходительный?
И скорее наоборот, поскольку эта программа работает в Debian Wheezy.
Сейчас я её скомпилировал вызовом g++, ни одного сообщения не было.

М.б. аргумент в вызове sendto и портится, но почему он не портится,
если дальше нет вызова gettimeofday()?

До сих пор не было проблем с передачей агрумента через int-переменную.

Да, приведение адреса sockaddr_in к адресу sockaddr - костыль, но таков интерфейс
функций, использующих sockaddr_in, так что я тут ни при чём.

Меня в данном случае ничего не смущает, я делаю, как сказано в man.

Это была книга Робачевского, 1-е издание. Но у меня есть и другие.

Я и сам вижу, что нечто портится из-за присутствия gettimeofday().
Вот узнать бы, что именно. И я не знаю, что такое UB, да и многое другое.

Пётр.

Пётр.

58

s.xbatob пишет:

Если хотите поковыряться в чужом и не слишком аккуратном коде - попробуйте.

обычно это сразу видно. Ну не увижу, пусть сам разбирается.

s.xbatob пишет:

Но по-прежнему ставлю на то, что бага в коде программы, а вовсе не в системе.

это очевидно, и не нуждается в обсуждении.

s.xbatob пишет:

Только вопрос изначально был о конкретной баге, приводящей к краху. А обсуждение съехало на светские разговоры о стиле программирования.

с таким "стилем" программирования, проблема может быть где угодно. Я на вскидку вижу 2 десятка потенциально опасных мест. В каком именно месте проблема — не знаю. Но очевидно, что исправлять нужно ВСЁ.

Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

59

Peter пишет:

Недавно где-то спрашивали, зачем эта конструкция

это уже 30 лет спрашивают. Сколько можно-то?
Фишка в том, что этот хак уже 15 лет неактуален.

Peter пишет:

врод бы трбовалось именно do..while.

do{}while() это единственное, что нужно заканчивать точкой с запятой.
ну вот вам, не ищите:

#define INIT_LIST_HEAD(ptr) do { \
    (ptr)->next = (ptr); (ptr)->prev = (ptr); \
} while (0)
if (doit) 
   INIT_LIST_HEAD(x);
 else 
   displayError(x);

http://stackoverflow.com/questions/9238 … ne-a-macro

Проблема в том, что тут необходимы {такие скобки}, но после них нельзя ставить точку с запятой. А после макроса — хочется, как после функции. Но если поставить, компилятор будет ругаться.

Вот потому ставят do{}while(0), тут как раз «;» нужна.

Этот пример не слишком полезен, потому что можно так написать:

#define INIT_LIST_HEAD(ptr) (ptr)->next=(ptr), (ptr)->prev=(ptr)

Но вот засунуть в макрос такую функцию:

TYPE swap(TYPE* x, TYPE* y)
{
  TYPE tmp = *x;
  *x = *y;
  *y = tmp;
}

уже не получится, ибо нужна закрытая область действия для временной переменной. Ну и конечно сишка не умеет шаблонных функций, потому, если хочется такое быдлокодить в сишке, то приходится юзать сей хак.

Да, не спрашивайте свою маму, почему ей сняться кошмары. Это вы виноваты: не надо было такой код публиковать, те, кто этот код решаться использовать, вашу маму вспоминают совсем не в контексте программирования…

Peter пишет:

А что, Ubuntu настолько дружественный дистрибутив или там gcc особенно снисходительный?

просто она чуть другая. Скорее всего версия glibc более новая. Я так подозреваю, что в Slackware-current будет тоже самое, ибо там glibc как в убунте.

Peter пишет:

М.б. аргумент в вызове sendto и портится, но почему он не портится,
если дальше нет вызова gettimeofday()?

киньте наконец бинарник проблемный, меня самого это вангование достало.

Peter пишет:

До сих пор не было проблем с передачей агрумента через int-переменную.

ох… Вам везёт как утопленнику.

Peter пишет:

Да, приведение адреса sockaddr_in к адресу sockaddr - костыль, но таков интерфейс
функций, использующих sockaddr_in, так что я тут ни при чём.

В когда-нить прыгали по лестнице на костылях? А я прыгал, к счастью — без костылей, они мне не нужны. Я к тому, что если таки костыли необходимы, то ходите осторожно, это же не ноги, можно и шею свернуть.

Peter пишет:

Меня в данном случае ничего не смущает, я делаю, как сказано в man.

совсем не так. Я видел тот пример. Чем отличается — я уже написал.

Peter пишет:

И я не знаю, что такое UB

ну с этого и надо было начинать.

Ответить на этот вопрос очень сложно. Русская вика как обычно не осилила, но всё-же ссылку я приведу для полноты: https://ru.wikipedia.org/wiki/%D0%9D%D0 … 0%B8%D0%B5

В английской вике http://en.wikipedia.org/wiki/Undefined_behavior есть простые примеры, но вы наверняка скажете, что "ко мне это не относится!".

Также я нашёл неплохую статью здесь: http://blog.llvm.org/2011/05/what-every … -know.html (ангйская вика тоже УГ, но там есть годные ссылки).

Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

60

Благодарю за разъяснение насчёт do{}...while(), в fido7.ru.linux была 1-я часть,
насчёт ';', но не было дальнейшего.

А зачем именно мой бинарник? Т.е. я понимаю, зачем, но я вовсе не прошу кого-то в нём ковыряться.
Если есть ошибка в тексте, она может быть обнаружена при его анализе. А компилирую я командой

gcc -Wall -O3 -o $1.elf -mtune=generic $1.c

где $1 это параметр скрипта с этой единственной командой.
Думаю, нетрудно догадаться, что он является именем файла с текстом программы без расширения.
-O3 я использую всегда, и в Qt тоже.

Пётр.

Пётр.