Вот очень простой тестовый пример:
int a __attribute__ ((section("section")));
int b __attribute__ ((section("section")));
int c __attribute__ ((section("section")));
Если я скомпилирую этот файл с GCC 8 без оптимизации и дампа объектного файла, я получу переменные в точном порядке, как в исходном файле:
$ gcc -c order.c
$ nm -n order.o
0000000000000000 D a
0000000000000004 D b
0000000000000008 D c
Однако, если я включаю оптимизацию (любой уровень), переменные обращаются в памяти:
$ gcc -O -c order.c
$ nm -n order.o
0000000000000000 D c
0000000000000004 D b
0000000000000008 D a
Поскольку мне нужно хранить согласованные адреса различных переменных в определенном разделе памяти для разных версий программы, я решил поместить все эти переменные в один и тот же исходный файл. Это для встроенного проекта, и раздел памяти, который я использую, имеет резервный аккумулятор, поэтому его содержимое не теряется при выключении устройства. Однако мне также нужно, чтобы адреса «старых» объектов оставались постоянными, и я не хочу, чтобы они менялись при добавлении некоторых «новых» объектов.
Так что мне интересно, является ли это конкретное поведение GCC чем-то, что я мог бы контролировать с помощью любого флага компилятора (кроме отключения оптимизации [;), и является ли это чем-то непротиворечивым в разных версиях GCC? Например, можно ли предположить, что в GCC 11, в 2022 году, порядок переменных в памяти по-прежнему будет обратным порядку в исходном файле, или, возможно, когда-нибудь порядок будет отличаться от сегодняшнего в GCC 8?