ALT Linux Team development discussions
 help / color / mirror / Atom feed
* [devel] вопрос по языку Си - порядок вычисления операндов
@ 2009-10-01  1:24 Alexey Tourbin
  2009-10-01  5:00 ` Damir Shayhutdinov
                   ` (2 more replies)
  0 siblings, 3 replies; 13+ messages in thread
From: Alexey Tourbin @ 2009-10-01  1:24 UTC (permalink / raw)
  To: devel

[-- Attachment #1: Type: text/plain, Size: 4217 bytes --]

У нас в rpm есть такой код.

lib/depends.h:
   108  typedef /*@abstract@*/ struct availableList_s {
   109  /*@owned@*/ /*@null@*/ struct availablePackage * list;  /*!< Set of packages. */
   110      struct availableIndex index;        /*!< Set of available items. */
   111      int delta;                          /*!< Delta for pkg list reallocation. */
   112      int size;                           /*!< No. of pkgs in list. */
   113      int alloced;                        /*!< No. of pkgs allocated for list. */
   114      int numDirs;                        /*!< No. of directories. */
   115  /*@owned@*/ /*@null@*/ dirInfo dirs;    /*!< Set of directories. */
   116  } * availableList;
...

lib/depends.c:
   213  static /*@exposed@*/ struct availablePackage *
   214  alAddPackage(availableList al,
   215                  Header h, /*@null@*/ /*@dependent@*/ const void * key,
   216                  /*@null@*/ FD_t fd, /*@null@*/ rpmRelocation * relocs)
   217          /*@modifies al, h @*/
   218  {
   219      HGE_t hge = (HGE_t)headerGetEntryMinMemory;
   220      HFD_t hfd = headerFreeData;
   221      rpmTagType dnt, bnt;
   222      struct availablePackage * p;
   223      rpmRelocation * r;
   224      int i;
   225      int_32 * dirIndexes;
   226      const char ** dirNames;
   227      int numDirs, dirNum;
   228      int * dirMapping;
   229      struct dirInfo_s dirNeedle;
   230      dirInfo dirMatch;
   231      int first, last, fileNum;
   232      int origNumDirs;
   233      int pkgNum;
   234  
   235      if (al->size == al->alloced) {
   236          al->alloced += al->delta;
   237          al->list = xrealloc(al->list, sizeof(*al->list) * al->alloced);
   238      }
...
   703  int rpmtransAddPackage(rpmTransactionSet ts, Header h, FD_t fd,
   704                          const void * key, int upgrade, rpmRelocation * relocs)
   705  {
   706      HGE_t hge = (HGE_t)headerGetEntryMinMemory;
   707      HFD_t hfd = headerFreeData;
   708      rpmTagType ont, ovt;
   709      /* this is an install followed by uninstalls */
   710      const char * name;
   711      int count;
   712      const char ** obsoletes;
   713      int alNum;
   714  
   715      /*
   716       * FIXME: handling upgrades like this is *almost* okay. It doesn't
   717       * check to make sure we're upgrading to a newer version, and it
   718       * makes it difficult to generate a return code based on the number of
   719       * packages which failed.
   720       */
   721      if (ts->orderCount == ts->orderAlloced) {
   722          ts->orderAlloced += ts->delta;
   723          ts->order = xrealloc(ts->order, sizeof(*ts->order) * ts->orderAlloced);
   724      }
   725      ts->order[ts->orderCount].type = TR_ADDED;
   726      if (ts->addedPackages.list == NULL)
   727          return 0;
   728  
   729      alNum = alAddPackage(&ts->addedPackages, h, key, fd, relocs) -
   730                  ts->addedPackages.list;
   731      ts->order[ts->orderCount++].u.addedIndex = alNum;
...

Вопрос касается строк 729-730.  Следите за движением рук.

ts->addedPackages -- это некоторая структура данных, которая содержит
ts->addedPackages.list -- указатель на массив, выделяемый в куче.
Функция alAddPackage() добавляет новый элемент в этот массив и возвращает
на него указатель.  Соответственно (по правилам типизированной адресной
арифметики) переменная alNum -- это будет индекс последнего добавленного
элемента в массиве.

Но!  Когда массив становится слишком маленьким, функция alAddPackage()
делает realloc этого массива (строка 237).  Соотвественно, адрес массива
ts->addedPackages.list может измениться.

Теперь посмотрим на вычитание указателей в строках 729-730.  Левый
операнд вычитания может изменить ts->addedPackages.list, а правым
операндом является сам ts->addedPackages.list.  Получается, что этот
код зависит от порядка вычисления операндов -- а именно, может
использоваться либо старое значение ts->addedPackages.list, либо
уже новое значение.

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

[-- Attachment #2: Type: application/pgp-signature, Size: 198 bytes --]

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [devel] вопрос по языку Си - порядок вычисления операндов
  2009-10-01  1:24 [devel] вопрос по языку Си - порядок вычисления операндов Alexey Tourbin
@ 2009-10-01  5:00 ` Damir Shayhutdinov
  2009-10-01  5:02 ` Kirill A. Shutemov
  2009-10-01  8:31 ` Kharitonov A. Dmitry
  2 siblings, 0 replies; 13+ messages in thread
From: Damir Shayhutdinov @ 2009-10-01  5:00 UTC (permalink / raw)
  To: ALT Linux Team development discussions

> Теперь посмотрим на вычитание указателей в строках 729-730.  Левый
> операнд вычитания может изменить ts->addedPackages.list, а правым
> операндом является сам ts->addedPackages.list.  Получается, что этот
> код зависит от порядка вычисления операндов -- а именно, может
> использоваться либо старое значение ts->addedPackages.list, либо
> уже новое значение.
>
> Воопрос соответствено насколько легален этот код, и вообще любая
> нетривиальная информация на эту тему.

Сделал тест:

#include <stdio.h>

static int change(int* p)
{
	*p = *p + 1;
	return *p;
}

void main(void)
{
	int a = 100;
	int b = change(&a) - a;
	printf("a=%d, b=%d\n", a, b);
}

После компиляции и запуска получается что b = 0; Что с -O0, что с -O2,
что с -O3.

Под рукой нет стандарта С, чтобы уточнить, но по крайней мере для gcc
этот код, похоже, легален.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [devel] вопрос по языку Си - порядок вычисления операндов
  2009-10-01  1:24 [devel] вопрос по языку Си - порядок вычисления операндов Alexey Tourbin
  2009-10-01  5:00 ` Damir Shayhutdinov
@ 2009-10-01  5:02 ` Kirill A. Shutemov
  2009-10-01  5:09   ` Kirill A. Shutemov
  2009-10-01  8:31 ` Kharitonov A. Dmitry
  2 siblings, 1 reply; 13+ messages in thread
From: Kirill A. Shutemov @ 2009-10-01  5:02 UTC (permalink / raw)
  To: ALT Linux Team development discussions

2009/10/1 Alexey Tourbin <at@altlinux.ru>:
> У нас в rpm есть такой код.
>
> lib/depends.h:
>   108  typedef /*@abstract@*/ struct availableList_s {
>   109  /*@owned@*/ /*@null@*/ struct availablePackage * list;  /*!< Set of packages. */
>   110      struct availableIndex index;        /*!< Set of available items. */
>   111      int delta;                          /*!< Delta for pkg list reallocation. */
>   112      int size;                           /*!< No. of pkgs in list. */
>   113      int alloced;                        /*!< No. of pkgs allocated for list. */
>   114      int numDirs;                        /*!< No. of directories. */
>   115  /*@owned@*/ /*@null@*/ dirInfo dirs;    /*!< Set of directories. */
>   116  } * availableList;
> ...
>
> lib/depends.c:
>   213  static /*@exposed@*/ struct availablePackage *
>   214  alAddPackage(availableList al,
>   215                  Header h, /*@null@*/ /*@dependent@*/ const void * key,
>   216                  /*@null@*/ FD_t fd, /*@null@*/ rpmRelocation * relocs)
>   217          /*@modifies al, h @*/
>   218  {
>   219      HGE_t hge = (HGE_t)headerGetEntryMinMemory;
>   220      HFD_t hfd = headerFreeData;
>   221      rpmTagType dnt, bnt;
>   222      struct availablePackage * p;
>   223      rpmRelocation * r;
>   224      int i;
>   225      int_32 * dirIndexes;
>   226      const char ** dirNames;
>   227      int numDirs, dirNum;
>   228      int * dirMapping;
>   229      struct dirInfo_s dirNeedle;
>   230      dirInfo dirMatch;
>   231      int first, last, fileNum;
>   232      int origNumDirs;
>   233      int pkgNum;
>   234
>   235      if (al->size == al->alloced) {
>   236          al->alloced += al->delta;
>   237          al->list = xrealloc(al->list, sizeof(*al->list) * al->alloced);
>   238      }
> ...
>   703  int rpmtransAddPackage(rpmTransactionSet ts, Header h, FD_t fd,
>   704                          const void * key, int upgrade, rpmRelocation * relocs)
>   705  {
>   706      HGE_t hge = (HGE_t)headerGetEntryMinMemory;
>   707      HFD_t hfd = headerFreeData;
>   708      rpmTagType ont, ovt;
>   709      /* this is an install followed by uninstalls */
>   710      const char * name;
>   711      int count;
>   712      const char ** obsoletes;
>   713      int alNum;
>   714
>   715      /*
>   716       * FIXME: handling upgrades like this is *almost* okay. It doesn't
>   717       * check to make sure we're upgrading to a newer version, and it
>   718       * makes it difficult to generate a return code based on the number of
>   719       * packages which failed.
>   720       */
>   721      if (ts->orderCount == ts->orderAlloced) {
>   722          ts->orderAlloced += ts->delta;
>   723          ts->order = xrealloc(ts->order, sizeof(*ts->order) * ts->orderAlloced);
>   724      }
>   725      ts->order[ts->orderCount].type = TR_ADDED;
>   726      if (ts->addedPackages.list == NULL)
>   727          return 0;
>   728
>   729      alNum = alAddPackage(&ts->addedPackages, h, key, fd, relocs) -
>   730                  ts->addedPackages.list;
>   731      ts->order[ts->orderCount++].u.addedIndex = alNum;
> ...
>
> Вопрос касается строк 729-730.  Следите за движением рук.
>
> ts->addedPackages -- это некоторая структура данных, которая содержит
> ts->addedPackages.list -- указатель на массив, выделяемый в куче.
> Функция alAddPackage() добавляет новый элемент в этот массив и возвращает
> на него указатель.  Соответственно (по правилам типизированной адресной
> арифметики) переменная alNum -- это будет индекс последнего добавленного
> элемента в массиве.
>
> Но!  Когда массив становится слишком маленьким, функция alAddPackage()
> делает realloc этого массива (строка 237).  Соотвественно, адрес массива
> ts->addedPackages.list может измениться.
>
> Теперь посмотрим на вычитание указателей в строках 729-730.  Левый
> операнд вычитания может изменить ts->addedPackages.list, а правым
> операндом является сам ts->addedPackages.list.  Получается, что этот
> код зависит от порядка вычисления операндов -- а именно, может
> использоваться либо старое значение ts->addedPackages.list, либо
> уже новое значение.
>
> Воопрос соответствено насколько легален этот код, и вообще любая
> нетривиальная информация на эту тему.

ISO/IEC 9899:TC2

6.5 Expressions

3 The grouping of operators and operands is indicated by the syntax.
Except as specified
later (for the function-call (), &&, ||, ?:, and comma operators), the
order of evaluation
of subexpressions and the order in which side effects take place are
both unspecified.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [devel] вопрос по языку Си - порядок вычисления операндов
  2009-10-01  5:02 ` Kirill A. Shutemov
@ 2009-10-01  5:09   ` Kirill A. Shutemov
  0 siblings, 0 replies; 13+ messages in thread
From: Kirill A. Shutemov @ 2009-10-01  5:09 UTC (permalink / raw)
  To: ALT Linux Team development discussions

2009/10/1 Kirill A. Shutemov <kirill@shutemov.name>:
> 2009/10/1 Alexey Tourbin <at@altlinux.ru>:
>> У нас в rpm есть такой код.
>>
>> lib/depends.h:
>>   108  typedef /*@abstract@*/ struct availableList_s {
>>   109  /*@owned@*/ /*@null@*/ struct availablePackage * list;  /*!< Set of packages. */
>>   110      struct availableIndex index;        /*!< Set of available items. */
>>   111      int delta;                          /*!< Delta for pkg list reallocation. */
>>   112      int size;                           /*!< No. of pkgs in list. */
>>   113      int alloced;                        /*!< No. of pkgs allocated for list. */
>>   114      int numDirs;                        /*!< No. of directories. */
>>   115  /*@owned@*/ /*@null@*/ dirInfo dirs;    /*!< Set of directories. */
>>   116  } * availableList;
>> ...
>>
>> lib/depends.c:
>>   213  static /*@exposed@*/ struct availablePackage *
>>   214  alAddPackage(availableList al,
>>   215                  Header h, /*@null@*/ /*@dependent@*/ const void * key,
>>   216                  /*@null@*/ FD_t fd, /*@null@*/ rpmRelocation * relocs)
>>   217          /*@modifies al, h @*/
>>   218  {
>>   219      HGE_t hge = (HGE_t)headerGetEntryMinMemory;
>>   220      HFD_t hfd = headerFreeData;
>>   221      rpmTagType dnt, bnt;
>>   222      struct availablePackage * p;
>>   223      rpmRelocation * r;
>>   224      int i;
>>   225      int_32 * dirIndexes;
>>   226      const char ** dirNames;
>>   227      int numDirs, dirNum;
>>   228      int * dirMapping;
>>   229      struct dirInfo_s dirNeedle;
>>   230      dirInfo dirMatch;
>>   231      int first, last, fileNum;
>>   232      int origNumDirs;
>>   233      int pkgNum;
>>   234
>>   235      if (al->size == al->alloced) {
>>   236          al->alloced += al->delta;
>>   237          al->list = xrealloc(al->list, sizeof(*al->list) * al->alloced);
>>   238      }
>> ...
>>   703  int rpmtransAddPackage(rpmTransactionSet ts, Header h, FD_t fd,
>>   704                          const void * key, int upgrade, rpmRelocation * relocs)
>>   705  {
>>   706      HGE_t hge = (HGE_t)headerGetEntryMinMemory;
>>   707      HFD_t hfd = headerFreeData;
>>   708      rpmTagType ont, ovt;
>>   709      /* this is an install followed by uninstalls */
>>   710      const char * name;
>>   711      int count;
>>   712      const char ** obsoletes;
>>   713      int alNum;
>>   714
>>   715      /*
>>   716       * FIXME: handling upgrades like this is *almost* okay. It doesn't
>>   717       * check to make sure we're upgrading to a newer version, and it
>>   718       * makes it difficult to generate a return code based on the number of
>>   719       * packages which failed.
>>   720       */
>>   721      if (ts->orderCount == ts->orderAlloced) {
>>   722          ts->orderAlloced += ts->delta;
>>   723          ts->order = xrealloc(ts->order, sizeof(*ts->order) * ts->orderAlloced);
>>   724      }
>>   725      ts->order[ts->orderCount].type = TR_ADDED;
>>   726      if (ts->addedPackages.list == NULL)
>>   727          return 0;
>>   728
>>   729      alNum = alAddPackage(&ts->addedPackages, h, key, fd, relocs) -
>>   730                  ts->addedPackages.list;
>>   731      ts->order[ts->orderCount++].u.addedIndex = alNum;
>> ...
>>
>> Вопрос касается строк 729-730.  Следите за движением рук.
>>
>> ts->addedPackages -- это некоторая структура данных, которая содержит
>> ts->addedPackages.list -- указатель на массив, выделяемый в куче.
>> Функция alAddPackage() добавляет новый элемент в этот массив и возвращает
>> на него указатель.  Соответственно (по правилам типизированной адресной
>> арифметики) переменная alNum -- это будет индекс последнего добавленного
>> элемента в массиве.
>>
>> Но!  Когда массив становится слишком маленьким, функция alAddPackage()
>> делает realloc этого массива (строка 237).  Соотвественно, адрес массива
>> ts->addedPackages.list может измениться.
>>
>> Теперь посмотрим на вычитание указателей в строках 729-730.  Левый
>> операнд вычитания может изменить ts->addedPackages.list, а правым
>> операндом является сам ts->addedPackages.list.  Получается, что этот
>> код зависит от порядка вычисления операндов -- а именно, может
>> использоваться либо старое значение ts->addedPackages.list, либо
>> уже новое значение.
>>
>> Воопрос соответствено насколько легален этот код, и вообще любая
>> нетривиальная информация на эту тему.
>
> ISO/IEC 9899:TC2
>
> 6.5 Expressions
>
> 3 The grouping of operators and operands is indicated by the syntax.
> Except as specified
> later (for the function-call (), &&, ||, ?:, and comma operators), the
> order of evaluation
> of subexpressions and the order in which side effects take place are
> both unspecified.
>

6.5.2.2 Function calls

12 EXAMPLE In the function call
(*pf[f1()]) (f2(), f3() + f4())
the functions f1, f2, f3, and f4 may be called in any order. All side
effects have to be completed before
the function pointed to by pf[f1()] is called

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [devel] вопрос по языку Си - порядок вычисления операндов
  2009-10-01  1:24 [devel] вопрос по языку Си - порядок вычисления операндов Alexey Tourbin
  2009-10-01  5:00 ` Damir Shayhutdinov
  2009-10-01  5:02 ` Kirill A. Shutemov
@ 2009-10-01  8:31 ` Kharitonov A. Dmitry
  2009-10-01  8:36   ` Kharitonov A. Dmitry
                     ` (2 more replies)
  2 siblings, 3 replies; 13+ messages in thread
From: Kharitonov A. Dmitry @ 2009-10-01  8:31 UTC (permalink / raw)
  To: ALT Linux Team development discussions

Alexey Tourbin wrote:
> У нас в rpm есть такой код.
>
> lib/depends.h:
>    108  typedef /*@abstract@*/ struct availableList_s {
>    109  /*@owned@*/ /*@null@*/ struct availablePackage * list;  /*!< Set of packages. */
>    110      struct availableIndex index;        /*!< Set of available items. */
>    111      int delta;                          /*!< Delta for pkg list reallocation. */
>    112      int size;                           /*!< No. of pkgs in list. */
>    113      int alloced;                        /*!< No. of pkgs allocated for list. */
>    114      int numDirs;                        /*!< No. of directories. */
>    115  /*@owned@*/ /*@null@*/ dirInfo dirs;    /*!< Set of directories. */
>    116  } * availableList;
> ...
>
> lib/depends.c:
>    213  static /*@exposed@*/ struct availablePackage *
>    214  alAddPackage(availableList al,
>    215                  Header h, /*@null@*/ /*@dependent@*/ const void * key,
>    216                  /*@null@*/ FD_t fd, /*@null@*/ rpmRelocation * relocs)
>    217          /*@modifies al, h @*/
>    218  {
>    219      HGE_t hge = (HGE_t)headerGetEntryMinMemory;
>    220      HFD_t hfd = headerFreeData;
>    221      rpmTagType dnt, bnt;
>    222      struct availablePackage * p;
>    223      rpmRelocation * r;
>    224      int i;
>    225      int_32 * dirIndexes;
>    226      const char ** dirNames;
>    227      int numDirs, dirNum;
>    228      int * dirMapping;
>    229      struct dirInfo_s dirNeedle;
>    230      dirInfo dirMatch;
>    231      int first, last, fileNum;
>    232      int origNumDirs;
>    233      int pkgNum;
>    234  
>    235      if (al->size == al->alloced) {
>    236          al->alloced += al->delta;
>    237          al->list = xrealloc(al->list, sizeof(*al->list) * al->alloced);
>    238      }
> ...
>    703  int rpmtransAddPackage(rpmTransactionSet ts, Header h, FD_t fd,
>    704                          const void * key, int upgrade, rpmRelocation * relocs)
>    705  {
>    706      HGE_t hge = (HGE_t)headerGetEntryMinMemory;
>    707      HFD_t hfd = headerFreeData;
>    708      rpmTagType ont, ovt;
>    709      /* this is an install followed by uninstalls */
>    710      const char * name;
>    711      int count;
>    712      const char ** obsoletes;
>    713      int alNum;
>    714  
>    715      /*
>    716       * FIXME: handling upgrades like this is *almost* okay. It doesn't
>    717       * check to make sure we're upgrading to a newer version, and it
>    718       * makes it difficult to generate a return code based on the number of
>    719       * packages which failed.
>    720       */
>    721      if (ts->orderCount == ts->orderAlloced) {
>    722          ts->orderAlloced += ts->delta;
>    723          ts->order = xrealloc(ts->order, sizeof(*ts->order) * ts->orderAlloced);
>    724      }
>    725      ts->order[ts->orderCount].type = TR_ADDED;
>    726      if (ts->addedPackages.list == NULL)
>    727          return 0;
>    728  
>    729      alNum = alAddPackage(&ts->addedPackages, h, key, fd, relocs) -
>    730                  ts->addedPackages.list;
>    731      ts->order[ts->orderCount++].u.addedIndex = alNum;
> ...
>
> Вопрос касается строк 729-730.  Следите за движением рук.
>
> ts->addedPackages -- это некоторая структура данных, которая содержит
> ts->addedPackages.list -- указатель на массив, выделяемый в куче.
> Функция alAddPackage() добавляет новый элемент в этот массив и возвращает
> на него указатель.  Соответственно (по правилам типизированной адресной
> арифметики) переменная alNum -- это будет индекс последнего добавленного
> элемента в массиве.
>
> Но!  Когда массив становится слишком маленьким, функция alAddPackage()
> делает realloc этого массива (строка 237).  Соотвественно, адрес массива
> ts->addedPackages.list может измениться.
>
> Теперь посмотрим на вычитание указателей в строках 729-730.  Левый
> операнд вычитания может изменить ts->addedPackages.list, а правым
> операндом является сам ts->addedPackages.list.  Получается, что этот
> код зависит от порядка вычисления операндов -- а именно, может
> использоваться либо старое значение ts->addedPackages.list, либо
> уже новое значение.
>
> Воопрос соответствено насколько легален этот код, и вообще любая
> нетривиальная информация на эту тему.
>   
Неоднократно натыкался на такое:
исходное выражение а+b+c
менялся порядок вычисления случайным образом
то так
а+(b+c)
то так
(а+b)+c
то так
(с+b)+a
естественно получалась случайно работающая программа. Багу ловил 3 месяца.
Во всех руководствах написано, что расстановка скобок принудительно 
должна обеспечивать порядок вычислений, но я опять таки натыкался на 
отступления и от этого. Разбивание выражения с применением промежуточной 
переменной однозначно определяло порядок, именно тот, который мне нужен. 
Промежуточная переменная в конечном коде в результате оптимизации исчезала.
Так же трудно уловимый баг связан с подстановкой в аргументы функции 
скрытых временных особенно, если эти аргументы помеченны модификатором 
const.



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [devel] вопрос по языку Си - порядок вычисления операндов
  2009-10-01  8:31 ` Kharitonov A. Dmitry
@ 2009-10-01  8:36   ` Kharitonov A. Dmitry
  2009-10-01  9:16   ` Kirill A. Shutemov
  2009-10-01  9:30   ` Led
  2 siblings, 0 replies; 13+ messages in thread
From: Kharitonov A. Dmitry @ 2009-10-01  8:36 UTC (permalink / raw)
  To: ALT Linux Team development discussions


>> Воопрос соответствено насколько легален этот код, и вообще любая
>> нетривиальная информация на эту тему.
Я считаю, что этот код не рабочий и передаю вам своё искреннее уважение, 
за обнаружение этой ошибки.


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [devel] вопрос по языку Си - порядок вычисления операндов
  2009-10-01  8:31 ` Kharitonov A. Dmitry
  2009-10-01  8:36   ` Kharitonov A. Dmitry
@ 2009-10-01  9:16   ` Kirill A. Shutemov
  2009-10-01  9:47     ` Kharitonov A. Dmitry
  2009-10-01  9:30   ` Led
  2 siblings, 1 reply; 13+ messages in thread
From: Kirill A. Shutemov @ 2009-10-01  9:16 UTC (permalink / raw)
  To: ALT Linux Team development discussions

2009/10/1 Kharitonov A. Dmitry <kharpost@rambler.ru>:
> Неоднократно натыкался на такое:
> исходное выражение а+b+c
> менялся порядок вычисления случайным образом
> то так
> а+(b+c)
> то так
> (а+b)+c
> то так
> (с+b)+a
> естественно получалась случайно работающая программа. Багу ловил 3 месяца.

Link?

> Во всех руководствах написано, что расстановка скобок принудительно должна
> обеспечивать порядок вычислений, но я опять таки натыкался на отступления и
> от этого. Разбивание выражения с применением промежуточной переменной
> однозначно определяло порядок, именно тот, который мне нужен. Промежуточная
> переменная в конечном коде в результате оптимизации исчезала.
> Так же трудно уловимый баг связан с подстановкой в аргументы функции скрытых
> временных особенно, если эти аргументы помеченны модификатором const.
>
> _______________________________________________
> Devel mailing list
> Devel@lists.altlinux.org
> https://lists.altlinux.org/mailman/listinfo/devel

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [devel] вопрос по языку Си - порядок вычисления операндов
  2009-10-01  8:31 ` Kharitonov A. Dmitry
  2009-10-01  8:36   ` Kharitonov A. Dmitry
  2009-10-01  9:16   ` Kirill A. Shutemov
@ 2009-10-01  9:30   ` Led
  2 siblings, 0 replies; 13+ messages in thread
From: Led @ 2009-10-01  9:30 UTC (permalink / raw)
  To: ALT Linux Team development discussions

On Thursday, 01 October 2009 11:31:39 Kharitonov A. Dmitry wrote:
> Неоднократно натыкался на такое:
> исходное выражение а+b+c
> менялся порядок вычисления случайным образом
> то так
> а+(b+c)
> то так
> (а+b)+c
> то так
> (с+b)+a
> естественно получалась случайно работающая программа. Багу ловил 3 месяца.
> Во всех руководствах написано, что расстановка скобок принудительно
> должна обеспечивать порядок вычислений,

Это ещё нужно постараться, чтобы найти такое рукоблу^H^H^Hводство. Ни в одном 
стандарте этого нет.

> но я опять таки натыкался на 
> отступления и от этого. Разбивание выражения с применением промежуточной
> переменной однозначно определяло порядок, именно тот, который мне нужен.
> Промежуточная переменная в конечном коде в результате оптимизации исчезала.
> Так же трудно уловимый баг связан с подстановкой в аргументы функции
> скрытых временных особенно, если эти аргументы помеченны модификатором
> const.

-- 
Led

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [devel] вопрос по языку Си - порядок вычисления операндов
  2009-10-01  9:16   ` Kirill A. Shutemov
@ 2009-10-01  9:47     ` Kharitonov A. Dmitry
  2009-10-01  9:51       ` Kirill A. Shutemov
  0 siblings, 1 reply; 13+ messages in thread
From: Kharitonov A. Dmitry @ 2009-10-01  9:47 UTC (permalink / raw)
  To: ALT Linux Team development discussions


> Link?
>
>   
К сожалению не дам. Не помню в каких программах это было и тем более в 
каком месте.
Собственно я такие баги стал замечать после прочтения книжки что-то там 
скользкие места с++ (я такую подлость просто не ожидал от компилятора).
Книжка в pdf где-то лежит, могу переслать в личку.



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [devel] вопрос по языку Си - порядок вычисления операндов
  2009-10-01  9:47     ` Kharitonov A. Dmitry
@ 2009-10-01  9:51       ` Kirill A. Shutemov
  2009-10-01 10:10         ` Kharitonov A. Dmitry
  0 siblings, 1 reply; 13+ messages in thread
From: Kirill A. Shutemov @ 2009-10-01  9:51 UTC (permalink / raw)
  To: ALT Linux Team development discussions

2009/10/1 Kharitonov A. Dmitry <kharpost@rambler.ru>:
>
>> Link?
>>
>>
>
> К сожалению не дам. Не помню в каких программах это было и тем более в каком
> месте.
> Собственно я такие баги стал замечать после прочтения книжки что-то там
> скользкие места с++ (я такую подлость просто не ожидал от компилятора).
> Книжка в pdf где-то лежит, могу переслать в личку.

Я думаю, что это не баг, а незнание инструмента. Порядок вычисления операндов
по стандарту никто не гарантирует. Было бы интересно посмотреть на конкретный
пример где есть "баг".

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [devel] вопрос по языку Си - порядок вычисления операндов
  2009-10-01  9:51       ` Kirill A. Shutemov
@ 2009-10-01 10:10         ` Kharitonov A. Dmitry
  2009-10-01 10:14           ` Damir Shayhutdinov
  0 siblings, 1 reply; 13+ messages in thread
From: Kharitonov A. Dmitry @ 2009-10-01 10:10 UTC (permalink / raw)
  To: ALT Linux Team development discussions

Kirill A. Shutemov wrote:
> 2009/10/1 Kharitonov A. Dmitry <kharpost@rambler.ru>:
>   
>>> Link?
>>>
>>>
>>>       
>> К сожалению не дам. Не помню в каких программах это было и тем более в каком
>> месте.
>> Собственно я такие баги стал замечать после прочтения книжки что-то там
>> скользкие места с++ (я такую подлость просто не ожидал от компилятора).
>> Книжка в pdf где-то лежит, могу переслать в личку.
>>     
>
> Я думаю, что это не баг, а незнание инструмента. Порядок вычисления операндов
> по стандарту никто не гарантирует. Было бы интересно посмотреть на конкретный
> пример где есть "баг".
>   
С позиции программиста это возможно это не баг. А вот с позиции 
пользователя -- это очевидный баг -- программа-то "глючит". Я в таких 
ситуациях принимаю позицию пользователя. Ну у меня вместо abc были 
вызовы функций, инкремент и пр.
Портя разночтение: какой баг вы имеете в виду баг приложения или баг 
компилятора? gcc в таких местах выдаёт предупреждения, правда не всегда, 
в одном месте, где я 3 месяца искал ошибку в "правильно" написанной 
программе предупреждений не было.



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [devel] вопрос по языку Си - порядок вычисления операндов
  2009-10-01 10:10         ` Kharitonov A. Dmitry
@ 2009-10-01 10:14           ` Damir Shayhutdinov
  2009-10-01 10:32             ` Kharitonov A. Dmitry
  0 siblings, 1 reply; 13+ messages in thread
From: Damir Shayhutdinov @ 2009-10-01 10:14 UTC (permalink / raw)
  To: ALT Linux Team development discussions

> С позиции программиста это возможно это не баг. А вот с позиции пользователя
> -- это очевидный баг -- программа-то "глючит". Я в таких ситуациях принимаю
> позицию пользователя. Ну у меня вместо abc были вызовы функций, инкремент и
> пр.

Есть простой совет - не злоупотреблять функциями с побочными
эффектами. Один побочный эффект на выражение - достаточно.

Так и карма  будет лучше, и волосы будут мягкими и шелковистыми.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [devel] вопрос по языку Си - порядок вычисления операндов
  2009-10-01 10:14           ` Damir Shayhutdinov
@ 2009-10-01 10:32             ` Kharitonov A. Dmitry
  0 siblings, 0 replies; 13+ messages in thread
From: Kharitonov A. Dmitry @ 2009-10-01 10:32 UTC (permalink / raw)
  To: ALT Linux Team development discussions

Damir Shayhutdinov wrote:
>> С позиции программиста это возможно это не баг. А вот с позиции пользователя
>> -- это очевидный баг -- программа-то "глючит". Я в таких ситуациях принимаю
>> позицию пользователя. Ну у меня вместо abc были вызовы функций, инкремент и
>> пр.
>>     
>
> Есть простой совет - не злоупотреблять функциями с побочными
> эффектами. Один побочный эффект на выражение - достаточно.
>
> Так и карма  будет лучше, и волосы будут мягкими и шелковистыми.
>   
все бы так думали.... Только всё чаще попадаются чужие программы, у 
авторов которых толи что-то с руками, толи у меня что-то не в порядке, 
приходится часто код переписывать -- когда чужая программа выходит из 
под меня -- ответственность уже несу я, а не дядя вася, который по этой 
программе уже отчитался, получил деньги и претензий не принимает, в 
акте-то написано, что претензий нет.



^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2009-10-01 10:32 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-10-01  1:24 [devel] вопрос по языку Си - порядок вычисления операндов Alexey Tourbin
2009-10-01  5:00 ` Damir Shayhutdinov
2009-10-01  5:02 ` Kirill A. Shutemov
2009-10-01  5:09   ` Kirill A. Shutemov
2009-10-01  8:31 ` Kharitonov A. Dmitry
2009-10-01  8:36   ` Kharitonov A. Dmitry
2009-10-01  9:16   ` Kirill A. Shutemov
2009-10-01  9:47     ` Kharitonov A. Dmitry
2009-10-01  9:51       ` Kirill A. Shutemov
2009-10-01 10:10         ` Kharitonov A. Dmitry
2009-10-01 10:14           ` Damir Shayhutdinov
2009-10-01 10:32             ` Kharitonov A. Dmitry
2009-10-01  9:30   ` Led

ALT Linux Team development discussions

This inbox may be cloned and mirrored by anyone:

	git clone --mirror http://lore.altlinux.org/devel/0 devel/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 devel devel/ http://lore.altlinux.org/devel \
		devel@altlinux.org devel@altlinux.ru devel@lists.altlinux.org devel@lists.altlinux.ru devel@linux.iplabs.ru mandrake-russian@linuxteam.iplabs.ru sisyphus@linuxteam.iplabs.ru
	public-inbox-index devel

Example config snippet for mirrors.
Newsgroup available over NNTP:
	nntp://lore.altlinux.org/org.altlinux.lists.devel


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git