gcc - 2 версии, различная обработка встроенных функций - PullRequest
3 голосов
/ 23 июня 2010

Недавно я столкнулся с проблемой в моем проекте. Обычно я компилирую его в gcc-4, но после попытки компилировать в gcc-3, я заметил другую обработку встроенных функций. Чтобы проиллюстрировать это, я создал простой пример:

main.c:

#include "header.h"
#include <stdio.h>

int main()
{
    printf("f() %i\n", f());
    return 0;
}

file.c:

#include "header.h"
int some_function()
{
    return f();
}

header.h

inline int f()
{
    return 2;
}

Когда я компилирую код в gcc-3.4.6 с помощью:

gcc main.c file.c -std=c99 -O2

Я получаю ошибку компоновщика (множественное определение f), то же самое, если убрать флаг -O2. Я знаю, что компилятору не нужно ничего вставлять, если он этого не хочет, поэтому я предположил, что он поместил f в объектный файл вместо того, чтобы вставлять его в случае как main.c, так и file.c, таким образом, ошибка множественного определения. Очевидно, я мог бы исправить это, сделав f статическим, а затем, в худшем случае, иметь несколько f в двоичном файле.

Но я попытался скомпилировать этот код в gcc-4.3.5 с помощью:

gcc main.c file.c -std=c99 -O2

И все работало нормально, поэтому я предположил, что более новый gcc встраивал f в обоих случаях, и в двоичном файле вообще не было функции f (проверено в gdb, и я был прав).

Однако, когда я убрал флаг -O2, я получил две неопределенные ссылки на int f(). И здесь я действительно не понимаю, что происходит. Похоже, что gcc предполагал, что f будет встроенным, поэтому он не добавил его в объектный файл, но позже (потому что -O2 не было) он решил генерировать вызовы этих функций вместо встраивания, и именно здесь ошибка компоновщика.

Теперь встает вопрос: как мне определять и объявлять простые и маленькие функции, которые я хочу встроить, чтобы их можно было использовать на протяжении всего проекта, не опасаясь проблем в различных компиляторах? И делает ли их все статичные правильные вещи? Или, может быть, gcc-4 не работает, и у меня никогда не должно быть нескольких определений встроенных функций в нескольких единицах перевода, если они не статичны?

1 Ответ

5 голосов
/ 23 июня 2010

Да, поведение было изменено с gcc-4.3 и далее. Gcc inline doc (http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Inline.html) Подробнее об этом.

Короткая история: обычный inline служит только для указания gcc (в любом случае в старой версии) встроенные вызовы из той же области файла. Тем не менее, это не говорит GCC, что все вызывающие абоненты будут из области видимости файла, таким образом, gcc также сохраняет связываемую версию f() вокруг: что объясняет вашу ошибку повторяющихся символов выше.

Gcc 4.3 изменил это поведение для совместимости с c99.

И, чтобы ответить на ваш конкретный вопрос:

Теперь встает вопрос: как мне определять и объявлять простые и маленькие функции, которые я хочу встроить, чтобы их можно было использовать на протяжении всего проекта, не опасаясь проблем в различных компиляторах? И делает ли их все статичные правильные вещи? Или, может быть, gcc-4 не работает, и у меня никогда не должно быть нескольких определений встроенных функций в нескольких единицах перевода, если они не статичны?

Если вы хотите переносимости между версиями gcc, используйте статические inline.

...