如何在Linux上对项目中的共享库(.so)进行修复?

5

我想快速修复项目中的一个.so库,只重新编译该库并替换原始库是否安全?还是必须重建和重新安装整个项目?还是要看情况而定?


难道不是由Makefile决定哪些组件需要重建吗?因此,您应该查看必须替换的文件。 - ott--
@ott:除非你告诉它,否则make不会知道或关心运行时的.so依赖项。给make提供决定ABI所需的内容绝对是不切实际的。 - Matt Joiner
5个回答

4
这要看情况。共享库需要与您的可执行文件二进制兼容

例如,

  1. 如果您更改了库中一个内部函数的行为,则可能不需要重新编译。
  2. 如果您更改了应用程序已知的结构体的大小(例如添加成员),则需要重新编译;否则,库和应用程序将认为结构体比实际小,并在库尝试读取应用程序未写入的额外未初始化成员时崩溃。
  3. 如果更改了任何从应用程序中可见的函数的参数类型或位置,则确实需要重新编译,因为库将尝试从堆栈中读取比应用程序放置的参数多的参数(在C中是这种情况,在C ++中参数类型是函数签名的一部分,所以应用程序会拒绝运行,而不是崩溃)。

生产发布的经验法则是:如果您没有有意识地注意到您正在维护二进制兼容性,或不确定什么是二进制兼容性,则应重新编译。


关于第3点:更改默认参数对ABI没有任何影响。对于cdecl调用(C中的默认值,以及GCC中的thiscall),调用方实际上会清理堆栈。传递比预期更多的参数也是可以的,但是对于从右到左的调用约定,则不能传递比预期更少的参数。 - Matt Joiner
@Matt,我没有提到“默认”参数,只是普通的参数。 :) 另外,在库的一侧可能会有更多的参数,而不是更少,因此库将尝试访问垃圾值。 - Alex B

1

使用动态库的目的就是这样:如果库中的某些内容需要更新,那么只需更新库,使用它的程序无需更改。如果您要更改的函数的签名不变且实现相同,则通常情况下这将是可以接受的。

当然,总会有一些边缘情况,即程序依赖于某个函数的未记录副作用,然后更改该函数的实现可能会改变副作用并破坏程序;但这就是生活。


1

如果您没有更改共享库的ABI,则只需重新构建并替换该库即可。


1

1

这要看情况而定。

不过,我假设你使用的是与其他代码相同的源代码和编译器,如果你只在一个.cpp文件中进行了更改,那么就没问题。

但是,如果你在头文件中更改接口(共享库和系统其他部分之间的接口),那就不行。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接