2013-12-03 2 views
10

Рассмотрим две немного разные версии одного и того же кода:оценки/доступа к структуре

struct s 
{ 
    int dummy[1]; 
}; 

volatile struct s s; 

int main(void) 
{ 
    s; 
    return 0; 
} 

и

struct s 
{ 
    int dummy[16]; 
}; 

volatile struct s s; 

int main(void) 
{ 
    s; 
    return 0; 
} 

Вот что я получаю с GCC 4.6.2 для них:

_main: 
     pushl %ebp 
     movl %esp, %ebp 
     andl $-16, %esp 
     call ___main 
     movl _s, %eax 
     xorl %eax, %eax 
     leave 
     ret 

     .comm _s, 4, 2 

и

_main: 
     pushl %ebp 
     movl %esp, %ebp 
     andl $-16, %esp 
     call ___main 
     xorl %eax, %eax 
     leave 
     ret 

     .comm _s, 64, 5 

Обратите внимание на отсутствие доступа к s во втором корпусе.

Является ли это ошибка компилятора или я просто имеет дело со следующим утверждением стандарта C и ССАГПЗ разработчиков просто выбрал такую ​​странную реализации, определенность и по-прежнему играю по правилам ?:

Что представляет собой доступ к объекту, который имеет изменчивый тип, определяется реализацией.

В чем причина этой разницы? Я, естественно, ожидал бы, что вся структура будет доступна (или не будет доступна, я не уверен), независимо от ее размера и того, что внутри него.

P.S. Что делает ваш компилятор (не-gcc или new gcc) в этом случае? (, пожалуйста, ответьте на этот последний вопрос в комментарии, если это единственная часть, на которую вы собираетесь обратиться, поскольку это не главный вопрос, который задают, но скорее вопрос любопытства).

+1

Я только что попробовал с GCC 4.8.0, и он похож: версия с одним словом по-прежнему получает одно чтение, но версия из 16 слов - нет. Если я говорю «s = s», хотя даже структура с 16 входами получает копию. –

+1

Это интересно: руководство GCC 4.6.0 специально вызывает _scalar volatiles_, в то время как в руководстве GCC 4.0.4 нет (два из них мне быстро удалось найти в Google). 4.6.0: http://gcc.gnu.org/onlinedocs/gcc-4.6.0/gcc/Volatiles.html 4.0.4: http://gcc.gnu.org/onlinedocs/gcc-4.0.4/gcc /Volatiles.html В вашем примере структура с одним int является «скалярным», а одно с 16 ints - нет. –

+1

@JoeZ Я не получаю доступ к скалярам, ​​находящимся внутри структуры, я обращаюсь ко всей структуре (или, как я думаю). –

ответ

3

Существует разница между C и C++ для этого вопроса, который объясняет, что происходит.

лязг-3.4

При составлении любого из этих фрагментов, как C++, излучаемая сборка не ссылки с в любом случае. На самом деле было выдано предупреждение для обоих:

volatile.c:8:2: warning: expression result unused; assign into a variable to force a volatile load [-Wunused-volatile-lvalue] s;

Эти предупреждения не были выпущены при компиляции в режиме C99. Как упоминалось в this blog post и this GCC wiki entry from the question comments, использование s в этом контексте вызывает преобразование lvalue-to-rvalue в C, но не в C++. Это подтверждается рассмотрением Clang AST для C, так как существует ImplicitCastExpr из LvalueToRValue, который не существует в AST, сгенерированном с C++. (AST не зависит от размера структуры).

Быстрый Grep источника Clang показывает это в излучении суммарных выражений:

case CK_LValueToRValue: 
// If we're loading from a volatile type, force the destination 
// into existence. 
if (E->getSubExpr()->getType().isVolatileQualified()) { 
    EnsureDest(E->getType()); 
    return Visit(E->getSubExpr()); 
} 

EnsureDest заставляет излучение слота стека, размер и типизированные для экспрессии. Поскольку оптимизаторам не разрешено удалять изменчивые обращения, они остаются в виде скалярной нагрузки/хранилища и memcpy соответственно как в IR, так и в asm. Это поведение, которое я ожидал бы, учитывая вышеизложенное.

GCC-4.8.2

Здесь я наблюдаю такое же поведение, как и в вопросе.Однако, когда я изменяю выражение от s; до s.dummy;, доступ не отображается ни в одной из версий. Я не знаком с внутренними системами gcc, поскольку я с LLVM, поэтому не могу предположить, почему это произойдет. Но, основываясь на вышеупомянутых наблюдениях, я бы сказал, что это ошибка компилятора из-за несогласованности.

+1

Спасибо. Я думаю, что разработчики gcc могут уйти с несогласованностью, потому что оценка целых структур (без их назначения друг другу) является чем-то редким явлением, имеет низкое практическое значение (не говоря уже о том, что потенциально много памяти или циклов кода или процессора может быть необходимо было прочитать структуру из памяти и что неясно, как следует читать члены профсоюза), а стандарт однозначно говорит: «Что представляет собой доступ к объекту, который имеет нестабильный тип, определяется реализацией». Я не думаю, что вопрос может или нуждается в дальнейшем уточнении. –

Смежные вопросы