Несовместимое изменение настройки по умолчанию при работе с tentative definition в lcc-1.28¶
Для информации: tentative definition - это, грубо говоря, глобальная переменная в языке C без extern, без static, без инициализатора
В компиляторах до gcc-9 включительно tentative definition при построении кода по умолчанию
строился как common (в терминах бинарного формата elf). Это означает, что допускалось
множественное определение таких переменных в разных файлах (compilation unit). Косвенно отсюда
вытекала возможность помещать tentative definition в заголовочные файлы. По опции -fno-common
такая возможность отключалась и множественное определение таких переменных приводило
к ошибке линковки. Таким образом, можно сказать, что в компиляторах до gcc-9 включительно
по умолчанию был включен режим -fcommon
/* Файл t1.c */
#include "t.h"
int main (void)
{
return 0;
}
/* Файл t2.c */
#include "t.h"
/* Файл t.h */
int x;
$ gcc-9 t1.c t2.c
<ok>
$ gcc-9 t1.c t2.c -fno-common
/tmp/ccl5WSjL.o:(.bss+0x0): multiple definition of `x'
/tmp/cc08riHC.o:(.bss+0x0): first defined here
collect2: error: ld returned 1 exit status
Начиная с gcc-10 изменился режим работы с tentative definition по умолчанию. Изменение
свелось к инвертированию значения по умолчанию для опциии -fcommon. Теперь по умолчанию
включен режим -fno-common. Т.е. по умолчанию использование множественного tentative
defintion приводит к ошибке линковки. Для повторения старого поведения нужно дополнительно
подавать опцию -fcommon
$ gcc-10 t1.c t2.c
/tmp/ccEJXUjw.o:(.bss+0x0): multiple definition of `x'
/tmp/cchsCQ1L.o:(.bss+0x0): first defined here
collect2: error: ld returned 1 exit status
$ gcc-10 t1.c t2.c -fcommon
<ok>
Симметричные изменения случились и в lcc при переходе от lcc-1.27 (номинально совместим с gcc-9) к lcc-1.28 (номинально совместим с gcc-11). Для того, чтобы в данном примере повторить старое поведение компилятора, нужно подать опцию -fcommon
# Старое поведение (lcc-1.27 и ниже)
$ /opt/mcst/bin/lcc t1.c t2.c
<ok>
# Новое поведение (lcc-1.28 и выше)
$ /opt/mcst/bin/lcc t1.c t2.c
/usr/bin/ld: /tmp/lcc_D1L2Bd.o:(.bss+0x0): multiple definition of `x'; /tmp/lcc_lh65le.o:(.bss+0x0): first defined here
# Новый компилятор с эмуляцией старого поведения
$ /opt/mcst/bin/lcc t1.c t2.c -fcommon
<ok>
