【发布时间】:2017-09-19 12:46:47
【问题描述】:
我有两个动态库和一个可执行文件:
- libOtherLibrary.so
- 这是一个由其他人编写的现有开源库。
- libMyLibrary.so
- 这是我自己的库,它依赖于 libOtherLibrary.so。
- exe
- 这是我自己的可执行文件,它依赖于这两个库。
作为查看何时调用特定函数的测试,我在 libOtherLibrary.so 的 内联函数 中添加了一条打印语句(代码细节无关紧要) :
template<class T>
inline void className<T>::clear() const
{
Info << "Hello World!" << endl; // My message!
if (isTmp() && ptr_)
{
if (ptr_->unique())
{
delete ptr_;
ptr_ = 0;
}
else
{
ptr_->operator--();
ptr_ = 0;
}
}
}
然后我重新编译 libOtherLibrary.so,然后重新编译 libMyLibrary.so。最后我重新链接(所以没有重新编译)exe。
结果是在 libMyLibrary.so 中发起的对 className<T>::clear() 的任何调用都使用了此内联方法的旧 实现,而对 className<T>::clear() 的任何调用都是由libOtherLibrary.so 使用了新的实现。
当我决定也重新编译 exe(然后链接它)时,结果是始终使用 new 实现。
我的问题是:谁能向我解释为什么 exe 需要重新编译,而不是仅仅重新链接?
即libOtherLibrary.so的函数className<T>::clear()的内联应该发生在libMyLibrary.so的编译阶段,不是吗?毕竟,它是 libMyLibrary.so 中包含的调用className<T>::clear() 的函数。然后我希望链接 exe 就足够了,因为 exe 不会调用这个特定的内联函数。单独的链接器将负责任何更改的 ABI 兼容性。
【问题讨论】:
-
首先,function-templates 隐含为
inline。其次,如果您的任何库中没有该 function-template 的ODR use,则尽管您进行了更改,编译器也不会发出任何新代码。每个翻译单元都会有一份您的function-template 实例化的单独副本。因此,当您不重新编译它时,旧的仍将被使用。现在,拥有两个独立且不同的副本违反了 ODR,但 C++ 不需要编译器来诊断它
标签: c++ gcc dynamic-library recompile inline-functions