gcc -u 符号编译器选项

Che*_*gar 5 c gcc compiler-flags

我们什么时候使用 gcc -u 编译器选项?您也可以举个例子吗?

https://gcc.gnu.org/onlinedocs/gcc-2.95.2/gcc_2.html 内容如下:

假装符号symbol未定义,以强制链接库模块来定义它。您可以多次使用带有不同符号的“-u”来强制加载其他库模块。

ble*_*ter 5

通常在对象链接期间,会搜索提供的模块(即,从编译的存档和其他目标文件中)是否存在未定义的符号,并且仅从提供的模块中提取最低限度满足整个未定义符号集所需的符号。

这在实践中意味着,如果您在目标文件中有一个函数 foo(),除非 foo() 在最终链接产品的其他地方使用,否则它将不会被包含在内。这通常是所需的行为。

如果您有一个模块提供了一些功能,这些功能未在最终链接产品的其他任何地方引用,但您仍然希望包含这些功能,那么情况又如何呢?(例如,也许这些函数被设计为直接从调试器调用)。这就是该-u选项派上用场的地方。它有效地告诉链接器存在对 foo() 的不满足引用,从而触发将其包含到最终链接的产品中,尽管代码中未引用该符号。

例子:

让我们定义两个函数foobar,并将每个函数放在一个单独的模块中,然后是一个仅引用 的短程序foo。尽管我们将 和 链接libfoo.alibbar.a程序中,但未包括对程序 ( a.out) 符号显示的检查。bar

foo.h:

void foo(void);
Run Code Online (Sandbox Code Playgroud)

foo.c:

void foo(void) { }
Run Code Online (Sandbox Code Playgroud)

酒吧.h:

void bar(void);
Run Code Online (Sandbox Code Playgroud)

酒吧.c:

void bar(void) { }
Run Code Online (Sandbox Code Playgroud)

主要.c:

#include "foo.h"
#include "bar.h"
int main(int argc, char** argv) {
    foo();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

建造:

gcc -c foo.c bar.c main.c
ar -r libfoo.a foo.o
ar -r libbar.a bar.o
# For macOS, replace -shared with -dylib
ld -shared main.o -L . -lfoo -lbar
nm -g --defined-only a.out

> T _main
> T _foo
Run Code Online (Sandbox Code Playgroud)

现在,如果我们只修改链接器阶段,并告诉它添加一个未定义的引用bar(使用其链接名称,该名称将带有下划线前缀),这次我们将bar在最终产品中找到,即使它没有在该程序:

# For macOS, replace -shared with -dylib
ld -shared -u _bar main.o -L . -lfoo -lbar
nm -g --defined-only a.out

> T _main
> T _foo
> T _bar
Run Code Online (Sandbox Code Playgroud)