假设我有一个库 somelib.a
,它由包管理器以二进制形式分发。这个库使用了只有头文件的库 anotherlib.hpp
。
如果我现在将我的程序链接到 somelib.a
,并且还使用 anotherlib.hpp
但使用不同的版本,那么这可能会导致 UB,如果 somelib.a
在其 anotherlib.hpp
header 中使用 include
的一部分。
但是如果 somelib.a
仅在其 cpp 文件中引用/使用 anotherlib.hpp
(所以我不知道它使用它们)会发生什么?我的应用程序和 somelib.a
之间的链接步骤是否会确保 somelib.a
和我的应用程序都将使用它们自己的 anotherlib.hpp
版本。
我问的原因是,如果我将程序的各个编译单元链接到最终程序,那么链接器会删除重复的符号(取决于它是否是内部链接)。因此,只有头的库通常以可以删除重复符号的方式编写。
一个最小的例子 somelib.a
构建在 nlohmann/json.hpp 版本 3.2 的系统上
somelib/somelib.h
namespace somelib {
struct config {
// some members
};
config read_configuration(const std::string &path);
}
somelib.cpp
#include <nlohmann/json.hpp>
namespace somelib {
config read_configuration(const std::string &path)
{
nlohmann::json j;
std::ifstream i(path);
i >> j;
config c;
// populate c based on j
return c;
}
}
应用程序构建在另一个系统上,nlohmann/json.hpp 3.5 版和 3.2 和 3.5 不兼容,然后应用程序链接到在 3.2 版系统上构建的
somelib.a
application.cpp
#include <somelib/somelib.h>
#include <nlohmann/json.hpp>
#include <ifstream>
int main() {
auto c = somelib::read_configuration("config.json");
nlohmann::json j;
std::ifstream i("another.json");
i >> j;
return 0;
}
最佳答案
使用静态库几乎没有任何区别。
C++ 标准规定,如果 在程序 中有一个内联函数(或类模板,或变量等)的多个定义,并且所有定义都不相同,那么您就有了 UB。
实际上,这意味着除非头库的 2 个版本之间的更改非常有限,否则您将拥有 UB。
例如,如果唯一的更改是空格更改、注释或添加新符号,那么您将不会有未定义的行为。但是,如果现有函数中的一行代码发生了更改,那么它就是 UB。
从 C++17 final working draft (n4659.pdf) :
关于c++ - 使用不同版本的仅 header 库是否会导致 UB,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55138082/