Подтвердить что ты не робот

Может ли GCC не жаловаться на ссылки undefined?

В какой ситуации GCC может не выдавать сообщение об ошибке "undefined ссылка" при попытке вызвать созданные функции?

Например, ситуация, когда этот код C скомпилирован и связан GCC:

void function()
{
    made_up_function_name();
    return;
}

... хотя made_up_function_name не присутствует в любом месте в коде (а не в заголовках, исходных файлах, декларациях или в сторонней библиотеке).

Может ли такой код быть принят и скомпилирован GCC при определенных условиях, не касаясь фактического кода? Если да, то что?

Спасибо.

EDIT: никакие предыдущие объявления или упоминания о made_up_function_name не присутствуют нигде. Это означает, что a grep -R всей файловой системы будет только показывать точную одну строку кода.

4b9b3361

Ответ 1

Да, можно избежать сообщения о неопределенных ссылках - используя --unresolved-symbols компоновщика --unresolved-symbols.

g++ mm.cpp -Wl,--unresolved-symbols=ignore-in-object-files

От man ld

--unresolved-символы = метод

Определите, как обращаться с неразрешенными символами. Есть четыре возможных значения для метода:

       ignore-all
           Do not report any unresolved symbols.

       report-all
           Report all unresolved symbols.  This is the default.

       ignore-in-object-files
           Report unresolved symbols that are contained in shared
           libraries, but ignore them if they come from regular object
           files.

       ignore-in-shared-libs
           Report unresolved symbols that come from regular object
           files, but ignore them if they come from shared libraries.  This
           can be useful when creating a dynamic binary and it is known
           that all the shared libraries that it should be referencing
           are included on the linker command line.

Поведение совместно используемых библиотек также может контролироваться параметром - [no-] allow-shlib-undefined.

Обычно компоновщик генерирует сообщение об ошибке для каждого сообщенного неразрешенного символа, но опция --warn-unresolved-symbols может изменить это на предупреждение.

Ответ 2

Если вы объявите прототип функции перед ее использованием, она будет скомпилирована. В любом случае ошибка при связывании останется.

void made_up_function_name();
void function()
{
    made_up_function_name();
    return;
}

Ответ 3

TL; DR Он не может жаловаться, но вы этого не хотите. Ваш код сработает, если вы заставите компоновщик игнорировать проблему. Это было бы контрпродуктивно.

Ваш код опирается на древний C (pre-C99), позволяющий неявным образом объявлять функции в своей точке использования. Ваш код семантически эквивалентен следующему коду:

void function()
{
    int made_up_function_name(...); // The implicit declaration

    made_up_function_name(); // Call the function
    return;
}

Компилятор справедливо жалуется, что объектный файл, содержащий скомпилированный function(), ссылается на символ, который больше нигде не найден. Вы должны исправить ее , обеспечивающей реализацию для made_up_function_name() , или удалив бессмысленный вызов. Это все там. Ничего не найдено.

Ответ 4

Если function() никогда не вызывается, он не может быть включен в исполняемый файл, а вызываемая из него функция также не выполняется.

Ответ 5

Когда вы создаете флаг компоновщика -r или --relocatable, он также не будет выводить никаких сообщений об ошибке "undefined".

Это связано с тем, что -r свяжет разные объекты в новом объектном файле, который будет связан на более позднем этапе.

Ответ 6

И тогда есть эта гадость с флагом -D, переданным GCC.

$cat undefined.c
void function()
{
    made_up_function_name();
    return;
}


int main(){
}

$gcc undefined.c -Dmade_up_function_name=atexit
$

Представьте, что вы ищете определение made_up_function_name - он пока еще не "делает вещи" в коде. Я не могу придумать хорошую причину, чтобы сделать это в коде.

Флаг -D - мощный инструмент для изменения кода во время компиляции.

Ответ 7

"Стандартный" алгоритм, в соответствии с которым работают лисингеры POSIX, открывает возможность того, что код будет компилироваться и связываться без каких-либо ошибок. Подробнее см. Здесь: fooobar.com/info/63742/...

Чтобы использовать эту возможность, объект файл, содержащий ваш function (пусть его называют f.o), должен быть помещен в библиотеку. Эта библиотека должна упоминаться в командной строке компилятора (и/или компоновщика), но к этому моменту ни один другой объектный файл (упомянутый ранее в командной строке) не должен был делать никаких вызовов на function или любую другую функцию, присутствующую в f.o. В таких случаях линкер не видит причин извлекать f.o из библиотеки. Linker полностью игнорирует f.o, полностью игнорирует function и, следовательно, остается полностью забытым о вызове made_up_function_name. Код будет компилироваться, даже если made_up_function_name не определен нигде.