Своей ужасной истории нет, но вот несколько цитат из Линуса Торвальдса (извините, если они уже есть в одной из ссылок в вопросе):
http://lkml.org/lkml/2003/2/26/158:
Date Wed, 26 Feb 2003 09:22:15 -0800 Тема Re: Некорректная компиляция без -fno-strict-aliasing From Jean Tourrilhes <>
On Wed, Feb 26, 2003 at 04:38:10PM +0100, Horst von Brand wrote:
Jean Tourrilhes <> said:
It looks like a compiler bug to me... Некоторые пользователи жаловались, что когда следующий код компилируется без -fno-strict-aliasing, порядок записи и memcpy инвертируется (что означает, что фиктивный len копируется в поток). Код (из linux/include/net/iw_handler.h) :
static inline char * iwe_stream_add_event(char * stream, /* Поток событий */ char * ends, /* Конец потока */ struct iw_event *iwe, /* Полезная нагрузка */ int event_len) /* Реальный размер полезной нагрузки */ { /* Проверьте, возможно ли это */ if((stream + event_len) < ends) { iwe->len = event_len; memcpy(stream, (char *) iwe, event_len); stream += event_len; } return stream; }
ИМХО, компилятор должен иметь достаточно контекста, чтобы знать, что переупорядочивание опасно. Любое предложение, как сделать этот простой код более пуленепробиваемым, приветствуется.
Компилятор волен считать, что char *stream и struct iw_event *iwe указывают на разные области памяти из-за строгого алиасинга.
Что верно, и что не является проблемой, на которую я жалуюсь.
(Заметка задним числом: этот код в порядке, но реализация memcpy
в Linux была макросом, который приводил к long *
для копирования в большие куски. При правильно определенном memcpy
, gcc -fstrict-aliasing
не может нарушить этот код. Но это означает, что вам нужен inline asm для определения ядра memcpy
, если ваш компилятор не знает, как превратить цикл копирования байтов в эффективный asm, что было в случае gcc до gcc7)
И комментарий Линуса Торвальда к вышесказанному:
Jean Tourrilhes wrote: >
По-моему, это похоже на ошибку компилятора...
Как вы думаете, почему ядро использует "-fno-strict-aliasing"?
Люди из gcc больше заинтересованы в попытках выяснить, что может быть разрешено спецификациями c99, чем в том, чтобы заставить вещи действительно работать. код алиасинга, в частности, даже не стоит включать, это просто невозможно невозможно разумно указать gcc, когда некоторые вещи могут псевдонимы.
Некоторые пользователи жаловались, что когда следующий код компилируется без -fno-strict-aliasing, порядок записи и memcpy инвертируется (что означает, что фиктивное значение len копируется в поток).
Проблема" заключается в том, что мы инлайним memcpy(), и в этот момент gcc не будет не будет заботиться о том, что он может использовать псевдонимы, так что он просто изменит порядок и заявят, что это их собственная вина. Несмотря на то, что нет никакого разумного способа сообщить об этом gcc.
Я пытался найти вменяемый способ несколько лет назад, и разработчики gcc действительно не заботились о реальном мире в этой области. Я был бы удивлен, если бы это изменилось, судя по ответам, которые я уже видел.
Я не собираюсь утруждать себя борьбой с этим.
Linus
http://www.mail-archive.com/linux-btrfs@vger.kernel.org/msg01647.html:
Type-based aliasing is stupid. Это настолько невероятно глупо, что даже не смешно. Оно сломано. И gcc взял это сломанное понятие и сделал его еще более сломанным, превратив его в "по букве закона", что не имеет никакого смысла.
...
Я точно знаю факт, что gcc переупорядочивал доступы на запись, которые были явно по одному и тому же адресу (статически). Gcc вдруг подумает, что
unsigned long a; a = 5; *(unsigned short *)&a = 4;
может быть переупорядочен, чтобы сначала установить его на 4 (потому что очевидно, что они не являются алиасами - читая стандарт), а затем, поскольку теперь присвоение 'a=5' было более поздним, присвоение 4 может быть полностью пропущено! И если кто-то пожалуется, что компилятор сошел с ума, люди из компилятора скажут: "Няа, няа, люди из стандартов сказали, что мы можем это сделать", совершенно не задаваясь вопросом, имеет ли это хоть какой-то смысл.