gcc - 我可以用动态符号表编译静态应用程序吗?

标签 gcc compiler-construction compilation linker

举个简单的例子:

void foo() {}

int main()
{
       return 0;
}

我构建它并查看动态符号表:

$ g++ test.cpp -o test
$ nm --dynamic test
0804849c R _IO_stdin_used
         w __gmon_start__
         U __libc_start_main

正如预期的那样,我没有看到 foo。所以我构建以包含未使用的符号。

$ gcc test.c -rdynamic -o test
$ nm --dynamic test
0804863c R _IO_stdin_used
         w _Jv_RegisterClasses
0804a010 A __bss_start
0804a008 D __data_start
         w __gmon_start__
080485e0 T __libc_csu_fini
08048570 T __libc_csu_init
         U __libc_start_main
0804a010 A _edata
0804a018 A _end
0804861c T _fini
08048638 R _fp_hw
08048438 T _init
080484a0 T _start
0804a008 W data_start
08048554 T foo
08048559 T main

您可以看到 foo 现在在符号表中。现在我构建一个静态版本。

$ gcc test.c -rdynamic -static -o test
$ nm --dynamic test
nm: test: No symbols

我的符号不见了,尽管我明确指定了它们。

根据 GCC 手册页:

-static On systems that support dynamic linking, this prevents linking with the shared libraries.

我的函数 foo() 不是共享库。

如果我扩展这个应用程序,它调用dlopen(),而我加载的库需要调用foo(),我的符号表不再包含引用 foo(),我的应用程序将失败。

这发生在我身上 recently .

为什么 -static 否定 -rdynamic,我该如何解决?

最佳答案

我认为可执行文件与 C 库静态链接的想法,但提供到共享库的导出可能是一个错误的概念。在这种情况下会发生什么?假设您的共享库分配了一些内存(使用它自己的 C 库副本),然后将其传递给可执行文件中的例程,该例程释放它(在 C 库的不同副本中)。这闻起来像个问题。如果您需要静态链接某些库,可以在这些库之前使用 -Wl,-Bstatic 选项来强制链接静态版本。

此外,如果您需要更多地控制正在发生的事情,最好有单独的编译和链接步骤,并直接使用 ld 进行链接步骤。它不一定对您正在使用的命令行选项有帮助,但我怀疑您可能会找到“有效”的东西,除非出现上述问题。

关于gcc - 我可以用动态符号表编译静态应用程序吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12367318/

相关文章:

java - 准备好发布 Java 程序

android - 提供的jar依赖不起作用

C++:使用 longjmp 和 setjmp 安全吗?

c - GCC 或 make 标志以禁止特定的标准库函数

c# - .net 库 (dll) 优化

c - Borland C 5.5 编译器不工作

ubuntu - 尝试在 Ubuntu 上使用 gcc 构建胖通用二进制文件时出错

c - "Variably modified ' 变量名 ' at file scope"大小在宏中定义

java - LL1 boolean 运算符语法实现递归下降解析器

java - 如何在 Java 中自动运行 GWT 编译?