Linux动态库(二)——动态库中访问外部符号问题

博主心里有一个问题:能不能在动态库内部访问到外部的符号吗?比如说:在main中定义了一个 int g_num,它能否在库里面进行访问呢?

于是博主立即写了一个小程序验证了一下:

t1.c

#include <stdio.h>

extern void print_num();
int g_num = 0;

int main()
{
    puts("--t1--");
    g_num = 12; 
    print_num();
    return 0;
}

print_num.c

#include <stdio.h>

extern int g_num;
void print_num()
{
    ++ g_num;
    printf("g_num=%d\n", g_num);
}

编译命令为:

gcc -o libprint_num.so -shared -fPIC print_num.c
gcc -o t1 t1.c -ldl -L. -lprint_num

运行示例:

LD_LIBRARY_PATH=$LD_LIBRARY_PATH:. ./t1

结果运行正常。

于是,博主兴致勃勃地进一步尝试:

t2.c

#include <dlfcn.h>
#include <stdio.h>

int g_num = 0;

typedef void (*Func)();

int main()
{
    puts("--t2--");
    g_num = 12; 
    void *h = dlopen("./libprint_num.so", RTLD_NOW);
    if (h == NULL) {
        puts(dlerror());
        return 0;
    }

    Func f = (Func)dlsym(h, "print_num");
    if (f != NULL) {
        (*f)();
    } else {
        puts("dlsym fail");
    }

    dlclose(h);
    return 0;
}

编译与运行命令:

gcc -o t2 t2.c -ldl
./t2

结果在 dlopen 时报错:

--t2--
./libprint_num.so: undefined symbol: g_num

怎么会这样呢?是 dlopen 时传的参数不对吗?

细心想想,t1属于启动时链接,t2属于是运行中链接。在启动时,loader读取t1文件,得到t1中的符号表,立即进行一次链接,没有什么问题。而程序一旦运行了起来,loader就已经完成了它的使命,为了节省空间很可能将符号表释放了。而这时将进行链接,就无法再链接成功了。这样理解正确吗?

如果正如上所述。那么一定应该有什么方式能让t2的符号表驻留在内存中,比如在t2编译时加什么参数。至少能让个别符号能驻留在内存中。否则,那就不好玩了。



经过一番波折,终于还是在 http://stackoverflow.com/ 中找到答案:http://stackoverflow.com/questions/480617/receive-undefined-symbol-error-when-loading-libary-with-dlopen

原文:

Correct solution is to add -rdynamic to the link command of the main executable. This will add appropriate option to ld (which, when using GNU ld, happens to be --export-dynamic).

Adding --export-dynamic directly is technically incorrect: it's a linker option, and so should be added as -Wl,--export-dynamic, or -Wl,-E. This is also less portable than -rdynamic (other linkers have an equivalent, but the option itself is different).

果然如我上面所猜测的那样。在编译executable程序时,要加 -rdynamic 参数。如下编译 t1:

g++ -o t2 t2.c -ldl -rdynamic

运行,成功。


思考:

加了这个 -rdynamic 后,会有多大的内存开销?这个在嵌入式软件开发中是要考虑的。

另一篇文章:http://stackoverflow.com/questions/8623884/gcc-debug-symbols-g-flag-vs-linkers-rdynamic-option


转载于:https://my.oschina.net/hevakelcj/blog/671924

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值