我在 linux 下, C++ 源码编译成了一个动态库,然后有一个正在执行的程序需要调用这个库,这个程序要运行很长时间。这时,我忽然想起来库里有一个函数错了,我修改了这个函数,并且重新编译了一下这个动态库。改完以后,发现我的程序并没有停止运行,也没有任何反馈信息。可又有一次,同样的情形,当我修改了库,重新编译了库以后,程序却报错了,跟内存有关的报错,详细信息当时没保存下来,那么问题来了:
请问什么情况下改变了库会导致调用它的程序报错退出?什么情况不会?
在程序没有报错退出的情况下,程序是在调用我修改以后的库函数吗?
本人不是 CS 专业,也不太懂编译原理相关理论,半路出家,现在搞一点科学计算,希望有经验的大大给一点指导,谢谢
1
wsy2220 2015-12-12 01:44:50 +08:00 1
如果你主程序是直接用 linker 链接到动态库的话,程序启动的同时就会链接到动态库,这时候修改库文件不会生效。
如果是在代码里用 dlopen 函数运行时链接的话,在调用 dlopen 之前修改或者 dlclose 之后修改,主程序看到的就是新的动态库。 看样子你应该没有用 dlopen 和 dlclose ,所以报错应该是旧版的库里有 bug 导致的。 |
2
wsy2220 2015-12-12 01:45:44 +08:00
可以参考 CSAPP 第 7 章。
|
3
giskard OP @wsy2220 感谢。请问我怎么才知道我是用 linker 还是 dlopen 呢?动态库是用 make 编译的,可执行程序是在 make 里用 -l 参数链接的,编译器是 g++。另,感谢推荐的书,我去看看第 7 章。
|
5
skydiver 2015-12-12 02:06:48 +08:00
可以学习一下,都有哪些修改会改变 ABI ,哪些修改不会改变 ABI 。这方面的文章很多的。
|
9
billlee 2015-12-12 11:41:03 +08:00
想到一个问题,替换动态库时,用 unlink 再 open 和直接 open O_TRUNC 是不是效果不一样啊?
楼主你是用什么命令替换的? |
10
forcecharlie 2015-12-12 12:15:41 +08:00
你修改的是 磁盘镜像,无论是 编译时 link 或者 dlopen, 运行的时候都会先将 so 文件加载到内存中,只要不是重新从磁盘中读取,那么就依然使用的是 旧的 so, 而 Windows 不一样, Windows 的 dll 会被锁定,然后,替换不了。
这也是为什么 linux rm -rf / 系统还能跑,重启起不来了。 |
11
xufang 2015-12-12 23:23:00 +08:00 via Android
楼上不懂装懂小学们去看淘宝团队技术博客,讲的很清楚可了。
一句话结论,看运气,可能崩溃。 |
12
xufang 2015-12-12 23:28:06 +08:00 via Android
什么叫以己昏昏,使人昭昭 。这贴就是。不过我猜即使我在此指出了关键点,估计也不会有人顺藤摸瓜去学习一个。
|
13
xufang 2015-12-12 23:41:37 +08:00 1
给小学生一点提示,崩溃和 linux 对共享库的延迟加载有关,所以知道为啥说看运气了不。
|