文档章节

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

临峰不畏
 临峰不畏
发布于 2016/05/09 03:08
字数 632
阅读 119
收藏 4

博主心里有一个问题:能不能在动态库内部访问到外部的符号吗?比如说:在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


© 著作权归作者所有

共有 人打赏支持
临峰不畏
粉丝 213
博文 187
码字总数 98583
作品 0
深圳
架构师
OBJ文件格式分析工具: objdump, nm,ar

首先简要阐述关于gcc、glibc和 binutils模块之间的关系 一、关于gcc、glibc和binutils模块之间的关系 1、gcc(gnu collect compiler)是一组编译工具的总称。它主要完成的工作任务是“预处理...

AlphaJay
2010/09/10
0
0
Qt动态库静态库的创建、使用、多级库依赖等详细说明

本文描述的是windows系统下,通过qtcreator在pro文件中添加动态库与静态库的方法: 1、添加动态库(直接添加动态库文件.dll,非子项目) 通过qtcreator创建动态库的方法就不在此处赘述了。 ...

苦涩的茶
08/16
0
0
linux 下动态链接库的制作与使用

linux 下动态链接库的制作与使用 linux 下动态链接库的制作与使用 动态链接库.so的编译与使用- - 动态库.so在linux下用c和c++编程时经常会碰到,最近在网站找了几篇文章介绍动态库的编译和链...

李东委
2014/10/08
0
0
用gcc编译成动态链接库的方法

通过一个例子来介绍如何生成一个动态库。假设有一个头文件sotest.h和三个C文件:testa.c、testb.c、testc.c /so_test.h/ include <stdio.h> include <stdlib.h> void test_a();void test_b(......

mj4738
2013/04/30
0
2
关于Linux静态库和动态库的分析

1.什么是库 在windows平台和linux平台下都大量存在着库。 本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。 由于windows和linux的本质不同,因此二者库的二进制是不...

YACHE
2011/07/04
0
0

没有更多内容

加载失败,请刷新页面

加载更多

linux 系统的运行级别

运行级别 运行级别 | 含义 0 关机 1 单用户模式,可以想象为windows 的安全模式,主要用于修复系统 2 不完全的命令模式,不含NFS服务 3 完全的命令行模式,就是标准的字符界面 4 系统保留 5 ...

Linux学习笔记
今天
2
0
学习设计模式——命令模式

任何模式的出现,都是为了解决一些特定的场景的耦合问题,以达到对修改封闭,对扩展开放的效果。命令模式也不例外: 命令模式是为了解决命令的请求者和命令的实现者之间的耦合关系。 解决了这...

江左煤郎
今天
3
0
字典树收集(非线程安全,后续做线程安全改进)

将500W个单词放进一个数据结构进行存储,然后进行快速比对,判断一个单词是不是这个500W单词之中的;来了一个单词前缀,给出500w个单词中有多少个单词是该前缀. 1、这个需求首先需要设计好数据结...

算法之名
昨天
15
0
GRASP设计模式

此文参考了这篇博客,建议读者阅读原文。 面向对象(Object-Oriented,OO)是当下软件开发的主流方法。在OO分析与设计中,我们首先从问题领域中抽象出领域模型,在领域模型中以适当的粒度归纳...

克虏伯
昨天
1
0
Coding and Paper Letter(四十)

资源整理。 1 Coding: 1.Tomislav Hengl撰写的非官方作者指南:Michael Gould•Wouter Gerritsma。 UnofficialGuide4Authors 2.R语言包rwrfhydro,社区贡献的工具箱,用于管理,分析和可视化...

胖胖雕
昨天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部