我可能在 GCC 或链接器中遇到过一个错误,当在运行时加载的共享库中有一个名为“error”的全局变量时,就会发生这种错误。乍一看,在名为“error”的文本段中似乎还有其他东西隐藏了这个变量。
foo.c:
#include <stdio.h>
const char *error = "error";
const char *error2 = "error2";
void bar(void)
{
printf("%p\n", error2);
printf("%p\n", error);
printf("%s\n", error2);
printf("%s\n", error);
}
主.c:
#include <stdio.h>
#include <dlfcn.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
void *lib_handle;
void (*fn)(void);
char *err;
lib_handle = dlopen("./libfoo.so", RTLD_LAZY);
if (!lib_handle)
{
fprintf(stderr, "%s\n", dlerror());
exit(1);
}
fn = dlsym(lib_handle, "bar");
if ((err = dlerror()) != NULL)
{
fprintf(stderr, "%s\n", err);
exit(1);
}
(*fn)();
dlclose(lib_handle);
return 0;
}
编译运行输出:
gcc -g -Wall -pedantic -fpic -O0 -c foo.c -o foo.o
gcc -shared -o libfoo.so foo.o
gcc main.c -Wall -fpic -o main -ldl
./main
0x7f62bc42c82b
0xfb8953f589555441
error2
Segmentation fault (core dumped)
这是工具链错误吗?如果是,是什么原因造成的,应该在哪里报告?
最佳答案
我相信这是设计好的,已经加载的符号将优先。例如如果已经加载了任何 error/error2(或 bar)符号,则不会重新定位共享库中的同名符号。做例如nm -D/lib/libc.so.6 |grep 错误。您的代码将引用那里的错误符号,无论它是什么。
但是,
$nm -D /lib/libc.so.6 |grep error`
42471670 W error
这表明 glibc 定义了一个 error
符号,但它是弱定义的。
这意味着如果您的代码在链接时定义了相同的符号,您的代码将覆盖任何弱
定义的符号。但是当你动态加载一个库时,这不会发生。
可以通过设置环境变量 LD_DYNAMIC_WEAK
来覆盖该行为 - 请参阅 man ld.so了解更多信息。
所以如果你像这样运行你的程序:
$ LD_DYNAMIC_WEAK=true ./main
它会起作用
关于c - 这是 GCC/链接器错误吗? (共享库中名为 'error' 的变量),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22377508/