Вопрос такой — что не так в этой программе? Подсказка — здесь имеется Undefined Behavior. Вопрос — Где?
Еще подсказка: GCC 3.4.1 и более поздние выдают следующий результат:
Это не глюк компилятора, компилятор ведет себя совершенно корректно. Просьба к гуру — подождать пару дней с ответом, чтобы любопытные, но менее опытные попытались сами докопаться до истины. А потом я хочу задать дополнительные вопросы, возникшие в связи с этим.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
MS> [...]
MS>
Правило введенное в С99 и запрещающее создание алиаса объекта с типом отличного от типа объекта-оригинала (ISO/IEC 9899 6.5/7) поддерживается в gcc 3.4.1 и выше на уровнях оптимизации начиная со 2-го. В данном случе sp не будет являться корректным алиасом для объекта *arg, потому компилятор вправе сгенерировать код, при котором sp не указывает на &(*arg).
MS>Вопрос такой — что не так в этой программе? Подсказка — здесь имеется Undefined Behavior. Вопрос — Где?
Мне вот что-то printf не нравится... "X" означает, что ожидается тип int. Если разрядность int отличается от 32, то и возникает Undefined behavior... Правда, является ли это причиной некорректной работы в данном случае, я не знаю...
MS>> [...]
MS>> АК>Правило введенное в С99 и запрещающее создание алиаса объекта с типом отличного от типа объекта-оригинала (ISO/IEC 9899 6.5/7) поддерживается в gcc 3.4.1 и выше на уровнях оптимизации начиная со 2-го. В данном случе sp не будет являться корректным алиасом для объекта *arg, потому компилятор вправе сгенерировать код, при котором sp не указывает на &(*arg).
В дополнение: В GCC это управляется с пом. ключа -fstrict-aliasing.
Здравствуйте, McSeem2, Вы писали:
MS>А потом я хочу задать дополнительные вопросы, возникшие в связи с этим.
Так вот, не могли бы знатоки популярно объяснить, когда точно возникает этот strict aliasing violation?
По идее, всегда при попытке преобразования указателя к другому типу.
Но malloc возващает void*, который по идее надо преобразовать к нужному типу. Что, это становится нелегальным?
Далее, например я делаю свой аллокатор, который, скажем, банально работает в статической памяти.
static char mem_pool[max_size];
. . .
int* allocate_int()
{
. . .
return (int*)(&mem_pool[index_aligned_to_int]); // To UB or not to UB?
}
Имеет ли место strict aliasing violation в этом случае?
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Здравствуйте, McSeem2, Вы писали:
MS>Но malloc возващает void*, который по идее надо преобразовать к нужному типу. Что, это становится нелегальным?
Нет, преобразование из void* к нужному типу легально. Тебе гарантировано, что void* вернет указатель на блок с наиболее общим alignment'ом.
MS>Далее, например я делаю свой аллокатор, который, скажем, банально работает в статической памяти. MS>
MS>static char mem_pool[max_size];
MS>. . .
MS>int* allocate_int()
MS>{
MS> . . .
MS> return (int*)(&mem_pool[index_aligned_to_int]); // To UB or not to UB?
MS>}
MS>
MS>Имеет ли место strict aliasing violation в этом случае?
Да. Так как поведение такого кода неопределено (откуда компилятор знает что у тебя действительно index_aligned_to_int правильный?). Но на практике обязано работать
Здравствуйте, Cyberax, Вы писали:
MS>>Имеет ли место strict aliasing violation в этом случае? C>Да. Так как поведение такого кода неопределено (откуда компилятор знает что у тебя действительно index_aligned_to_int правильный?). Но на практике обязано работать
Компилятор не может знать ничего про выравнивание в этом случае — это все на моей совести.
По-моему, они чего-то перемудрили с этим строгим алиасингом. Самое неприятное, что предупреждения может и не быть, но оптимизатор возьмет да выкинет реально необходимые операции.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Здравствуйте, McSeem2, Вы писали:
MS>>>Имеет ли место strict aliasing violation в этом случае? C>>Да. Так как поведение такого кода неопределено (откуда компилятор знает что у тебя действительно index_aligned_to_int правильный?). Но на практике обязано работать MS>Компилятор не может знать ничего про выравнивание в этом случае — это все на моей совести.
Поэтому с точки зрения Стандарта — это UB.
MS>По-моему, они чего-то перемудрили с этим строгим алиасингом. Самое неприятное, что предупреждения может и не быть, но оптимизатор возьмет да выкинет реально необходимые операции.
Можешь явно сказать компилятору, что ты знаешь что делаешь: (int*)(void*)(&someChar[..])
Здравствуйте, Андрей Коростелев, Вы писали:
АК>Здравствуйте, McSeem2, Вы писали:
АК>Правило введенное в С99 и запрещающее создание алиаса объекта с типом отличного от типа объекта-оригинала (ISO/IEC 9899 6.5/7) поддерживается в gcc 3.4.1 и выше на уровнях оптимизации начиная со 2-го. В данном случе sp не будет являться корректным алиасом для объекта *arg, потому компилятор вправе сгенерировать код, при котором sp не указывает на &(*arg).
Блин гавно какоето ... эт я не по поводу ответа , а по вышеописанному
MS>> [...]
MS>> АК>Правило введенное в С99 и запрещающее создание алиаса объекта с типом отличного от типа объекта-оригинала (ISO/IEC 9899 6.5/7) поддерживается в gcc 3.4.1 и выше на уровнях оптимизации начиная со 2-го. В данном случе sp не будет являться корректным алиасом для объекта *arg, потому компилятор вправе сгенерировать код, при котором sp не указывает на &(*arg).
Насколько я понимаю, в C++ стандарте такого ограничения нет. Тем не менее, GCC 3.4.4 для C++ генерирует такой же проблемный код, как и для C
McSeem2 прав -- такая паранойя. Если уж C/C++ позиционируются как языки для работы непосредственно с железом, то запрещение простого свопинга байт/слов выглядит полным маразмом.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
MS>> [...]
MS>> АК>Правило введенное в С99 и запрещающее создание алиаса объекта с типом отличного от типа объекта-оригинала (ISO/IEC 9899 6.5/7) поддерживается в gcc 3.4.1 и выше на уровнях оптимизации начиная со 2-го. В данном случе sp не будет являться корректным алиасом для объекта *arg, потому компилятор вправе сгенерировать код, при котором sp не указывает на &(*arg).
Т.е. получается, что sp будет указывать по непонятному адресу? Т.е. реально вообще получить Segmentation Fault?!!!
Правильно ли я понял?
Здравствуйте, eao197, Вы писали:
E>Насколько я понимаю, в C++ стандарте такого ограничения нет. Тем не менее, GCC 3.4.4 для C++ генерирует такой же проблемный код, как и для C
E>McSeem2 прав -- такая паранойя. Если уж C/C++ позиционируются как языки для работы непосредственно с железом, то запрещение простого свопинга байт/слов выглядит полным маразмом.
Вообще, такая проблема наблюдается на процессорах, адресация в которых к данным должна быть выравнена по границе 2, 4 и т.д. (8 не встречал)
Так вот, сразу же налетел на ARM (AT91RM9200) на выравнивание по границе кратной 2.
Потратил на это порядка несольких часов, просто ушли в холостую.
А произошло это из-за того,что надо было из буфера (char*)[1] получить uint32_t или наоборот в (char*)[1] положить uint32_t.
Тут бы по выравниванию памяти вообще механизм блокировок придумать какой-то было бы просто замечательно.
eao197 wrote:
> McSeem2 прав -- такая паранойя. Если уж C/C++ позиционируются как языки > для работы непосредственно с железом, то запрещение простого свопинга > байт/слов выглядит полным маразмом.
Маразмом является приведение неприводимого. А задача своппинга решается битовыми операциями.
Posted via RSDN NNTP Server 2.1 beta
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай