关于静态库和动态库的问题

iory_526 2009-04-07 04:13:09
我在别的地方看到的,自己不懂,在这里请教大虾了。
用例:现有一静态库(libdep.a),定义如下函数:

void func(void)
{
static int inited = 0;
if(!inited)
{
do_init();
inited = 1;
}
}

有两个动态库,分别命名为libref1.so 和 libref2.so,这两个动态库中分别调用了静态库libdep.a中的func函数. 动态库在编译的时候链接了静态库libdep.a

libref1.so中

void ref1_func(void)
{
func();
}

libref2.so中

void ref2_func(void)
{
func();
}

应用程序main函数中又调用动态库中的这两个函数:

int main(int argc,char**argv)
{
ref1_func();
ref2_func();
return 0;
}

程序运行发现 do_init()只被执行了一次,也就是说两个动态库中inited共享同一份拷贝.

但是如果在应用程序用,使用dlopen/dlsym来加载动态库

int main(int argc,char**argv)
{
void* handle1,*handle2;
void (*ref1_func)(void);
void (*ref2_func)(void);
handle1 = dlopen("libref1.so",RTLD_LAZY);
ref1_func = dlsym(handle1,"ref1_func");
handle2 = dlopen("libref2.so",RTLD_LAZY);
ref2_func = dlsym(handle2,"ref2_func");

ref1_func();
ref2_func();

dlclose(handle1);dlopen(handle2)
return 0;
}

用这种方式动态加载共享库,程序运行发现do_init()被执行了两次,也就是说inited在内存中有两份不一样的拷贝.

请问有人能解释一下在这两种情况下,静态变量inited的布局为何有如此差异吗?

谢谢
...全文
254 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
iory_526 2009-04-09
  • 打赏
  • 举报
回复
up
zangkannt 2009-04-08
  • 打赏
  • 举报
回复
up
zangkannt 2009-04-07
  • 打赏
  • 举报
回复
[Quote]
这就是启动时加载和运行时加载的区别。
启动时加载:so文件中的函数在代码区;
运行时加载:so文件中的…
[/Quote]
大牛,也就是说libref1.so和libref2.so确实都各自包含属于静态库libdep.a的函数、符号等。

启动加载时所有libdep.a的部分都被优化成一份,还是就static int inited被优化成了一份,因此怎么执行都是只调用init一次。这么理解对吗?

而动态加载你所说的“共享区”是什么概念啊?对于ELF怎么看哪个section是不是“共享”的?
dongpy 2009-04-07
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 zangkannt 的回复:]
可是,do_init()被分别静态连接到libref1.so和libref2.so啦,而在编译连接的时候分别连接的libref1.so和libref2.so。

难道编译器会很智能,判断到libref1.so和libref2.so都有do_init()的部分,直接合二为一了?

那按照这种说法使用dlopen时为何却执行了两次呢?

呵呵,想不明白。
[/Quote]
这就是启动时加载和运行时加载的区别。
启动时加载:so文件中的函数在代码区;
运行时加载:so文件中的函数在共享区。
chenzhp 2009-04-07
  • 打赏
  • 举报
回复
http://topic.csdn.net/t/20040823/16/3301580.html
这也是symbian系统所顾忌的。
zbing0203 2009-04-07
  • 打赏
  • 举报
回复
mark
zangkannt 2009-04-07
  • 打赏
  • 举报
回复
可是,do_init()被分别静态连接到libref1.so和libref2.so啦,而在编译连接的时候分别连接的libref1.so和libref2.so。

难道编译器会很智能,判断到libref1.so和libref2.so都有do_init()的部分,直接合二为一了?

那按照这种说法使用dlopen时为何却执行了两次呢?

呵呵,想不明白。
mengde007 2009-04-07
  • 打赏
  • 举报
回复
程序运行发现 do_init()只被执行了一次,那是因为一个进程只能加载一个库一次,第二次加载的时候只是对dll引用的计数+1;

65,211

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧