1

我可能在 GCC 或链接器中遇到了一个错误,当在运行时加载的共享库中有一个名为“错误”的全局变量时,就会发生这种错误。乍一看,在名为“error”的文本段中似乎有其他东西隐藏了这个变量。

富.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)

这是一个工具链错误吗?如果是这样,什么可能导致这种情况以及应该在哪里报告?

4

1 回答 1

2

我相信按照设计,已经加载的符号将优先。例如,如果已经加载了任何错误/错误2(或条形)符号,则共享库中相同命名的符号将不会被重新定位。执行例如 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

它会起作用的

于 2014-03-13T12:34:50.647 回答