V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
giskard
V2EX  ›  问与答

改变一个正在被调用的 C++动态库,对需要调用它,且当前正在执行的的程序有什么影响?

  •  
  •   giskard · 2015-12-12 01:34:27 +08:00 · 3676 次点击
    这是一个创建于 3307 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我在 linux 下, C++ 源码编译成了一个动态库,然后有一个正在执行的程序需要调用这个库,这个程序要运行很长时间。这时,我忽然想起来库里有一个函数错了,我修改了这个函数,并且重新编译了一下这个动态库。改完以后,发现我的程序并没有停止运行,也没有任何反馈信息。可又有一次,同样的情形,当我修改了库,重新编译了库以后,程序却报错了,跟内存有关的报错,详细信息当时没保存下来,那么问题来了:

    1. 请问什么情况下改变了库会导致调用它的程序报错退出?什么情况不会?

    2. 在程序没有报错退出的情况下,程序是在调用我修改以后的库函数吗?

    本人不是 CS 专业,也不太懂编译原理相关理论,半路出家,现在搞一点科学计算,希望有经验的大大给一点指导,谢谢

    14 条回复    2015-12-14 16:48:08 +08:00
    wsy2220
        1
    wsy2220  
       2015-12-12 01:44:50 +08:00   ❤️ 1
    如果你主程序是直接用 linker 链接到动态库的话,程序启动的同时就会链接到动态库,这时候修改库文件不会生效。
    如果是在代码里用 dlopen 函数运行时链接的话,在调用 dlopen 之前修改或者 dlclose 之后修改,主程序看到的就是新的动态库。

    看样子你应该没有用 dlopen 和 dlclose ,所以报错应该是旧版的库里有 bug 导致的。
    wsy2220
        2
    wsy2220  
       2015-12-12 01:45:44 +08:00
    可以参考 CSAPP 第 7 章。
    giskard
        3
    giskard  
    OP
       2015-12-12 01:56:50 +08:00
    @wsy2220 感谢。请问我怎么才知道我是用 linker 还是 dlopen 呢?动态库是用 make 编译的,可执行程序是在 make 里用 -l 参数链接的,编译器是 g++。另,感谢推荐的书,我去看看第 7 章。
    wsy2220
        4
    wsy2220  
       2015-12-12 02:01:16 +08:00
    @giskard 那就是直接用 linker(ld)链接了
    skydiver
        5
    skydiver  
       2015-12-12 02:06:48 +08:00
    可以学习一下,都有哪些修改会改变 ABI ,哪些修改不会改变 ABI 。这方面的文章很多的。
    skydiver
        6
    skydiver  
       2015-12-12 02:10:22 +08:00
    @wsy2220 你没说到点子上。 lz 的程序本身就是动态链接的,报错是因为改变了动态链接库的 ABI 导致。
    wsy2220
        7
    wsy2220  
       2015-12-12 02:22:58 +08:00
    @skydiver 动态链接也分情况啊,以楼主这种方式动态链接,主程序还在运行的时候修改是不生效的...
    skydiver
        8
    skydiver  
       2015-12-12 02:44:17 +08:00 via Android
    @wsy2220 确实,如果已经在运行了,覆盖 so 应该没影响……这个确实奇怪
    billlee
        9
    billlee  
       2015-12-12 11:41:03 +08:00
    想到一个问题,替换动态库时,用 unlink 再 open 和直接 open O_TRUNC 是不是效果不一样啊?
    楼主你是用什么命令替换的?
    forcecharlie
        10
    forcecharlie  
       2015-12-12 12:15:41 +08:00
    你修改的是 磁盘镜像,无论是 编译时 link 或者 dlopen, 运行的时候都会先将 so 文件加载到内存中,只要不是重新从磁盘中读取,那么就依然使用的是 旧的 so, 而 Windows 不一样, Windows 的 dll 会被锁定,然后,替换不了。
    这也是为什么 linux rm -rf / 系统还能跑,重启起不来了。
    xufang
        11
    xufang  
       2015-12-12 23:23:00 +08:00 via Android
    楼上不懂装懂小学们去看淘宝团队技术博客,讲的很清楚可了。

    一句话结论,看运气,可能崩溃。
    xufang
        12
    xufang  
       2015-12-12 23:28:06 +08:00 via Android
    什么叫以己昏昏,使人昭昭 。这贴就是。不过我猜即使我在此指出了关键点,估计也不会有人顺藤摸瓜去学习一个。
    xufang
        13
    xufang  
       2015-12-12 23:41:37 +08:00   ❤️ 1
    给小学生一点提示,崩溃和 linux 对共享库的延迟加载有关,所以知道为啥说看运气了不。
    giskard
        14
    giskard  
    OP
       2015-12-14 16:48:08 +08:00
    @xufang 我是幼稚园还没毕业的。。。请问大神,您提到的淘宝团队技术博客,可否给一个链接看看?我 Google 过了,不确定我找到的是不是大神说的那个
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1080 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 74ms · UTC 22:47 · PVG 06:47 · LAX 14:47 · JFK 17:47
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.