c - 这是 GCC/链接器错误吗? (共享库中名为 'error' 的变量)

标签 c ubuntu gcc gcc4.8

我可能在 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/

相关文章:

linux - 如何使目录下的所有文件在 linux 上都可读?

c - 如何在不强制转换的情况下取消引用 void 变量

c - 在矩阵链乘法中,访问二维数组(参数)错误

linux - 使用 tcp 2222 :22 to copy things 时,用于内核开发的 QEMU 引导不起作用

mysql - 与 XAMPP 相比,MariaDB Docker 容器中的 INSERT SQL 查询非常慢

c - 编译时出错 - 初始化程序中指定的未知字段

c - GCC 不会对从 void * 到 void ** 的隐式转换发出警告

c++ - SciLinux : libgfortran. so.3:找不到版本 'GFORTRAN_1.4'

c - f(n) = n + f(floor(n/2)) 是否有封闭形式?

c - tiva c 隐函数