不同版本的破坏者称为奇怪因素
Different versions of destructor called depending on strange factors
为什么以下代码生成这样的输出?
main.cpp ctor 0x24a4c30
test.cpp dtor 0x24a4c30
test.cpp
#include <boost/optional.hpp>
struct Test
{
Test()
{
printf("test.cpp ctor %pn", (void *) this);
}
~Test()
{
printf("test.cpp dtor %pn", (void *) this);
}
};
boost::optional< Test > t;
main.cpp
#include <memory>
struct Test
{
Test()
{
printf("main.cpp ctor %pn", (void *) this);
}
~Test()
{
printf("main.cpp dtor %pn", (void *) this);
}
};
int
main(void)
{
std::make_shared< Test >();
return 0;
}
用
编译g++ -std=c++11 -c test.cpp -o test.o
g++ -std=c++11 -c main.cpp -o main.o
g++ -std=c++11 test.o main.o
我解释了这种行为,即 test.o 提供test的 ctor&amp;然后,然后从 main.o 中丢弃重复的符号,但仅对 dtor 是正确的。如果我删除静态对象 t ,则会从 test.o 中丢弃符号,并且输出是下一个
main.cpp ctor 0x208ec30
main.cpp dtor 0x208ec30
如评论中所述,在两个链接的翻译单元中定义相同的符号违反了一个定义规则,而
只要每个程序都可能有一个以上的定义 定义出现在不同的翻译单元中 以下:类Type ,枚举类型,内联功能与外部功能 linkage ,外部链接的内联变量(自C 17(,类 模板,非静态功能模板,类的静态数据成员 模板,类模板的成员功能,部分模板 专业,概念(自C 20(,只要以下所有内容 是真的:
- 每个定义都由同一序列组成(通常,出现在同一标头文件中(
- [...]
如果满足了所有这些要求,则该程序的行为好像 整个程序中只有一个定义。否则, 行为不确定。(重点是我的(
观察到UB的结果不需要解释,也可能没有任何解释。
当然,这是公然的违规行为。但是,在外观更无辜的程序中可能会出现非常相似的情况(并导致奇怪而难以找到错误(。例如,当某些类声明更改时,针对较旧的单独编译对象链接。
相关文章:
- 为cl.exe(Visual Studio代码)指定命令行C++版本
- 导入库可以跨dll版本工作吗
- 在调用FreeLibrary后,释放动态链接到具有相同版本的CRT堆的DLL的内存
- 在clang++预处理器中确定gcc工具链版本
- 码头化的C++应用程序是否向后兼容早期的内核版本
- 不同的Visual Studio版本中缺少.dll
- 用符号版本替换对函数的所有调用
- luaL_dofile在已知良好的字节码上失败,可以使用未编译的版本
- 正在解码MSVC 32位版本的程序集(作业).没有手术做什么
- 我需要分发哪些版本的可再分发文件
- CV_OCL_RUN宏如何在OpenCV(版本3.4.5)的goodFeaturesToTrack实现中工作?
- 在运行时读取 libstdc++ 版本
- 如何声明一个可以在整个程序中使用的全局 2d 3d 4d .. 数组(堆版本)变量?
- FindPackageHandleStandardArgs.cmake:137 的 CMake 错误(消息):找不到 Boost (缺少:正则表达式)(找到合适的版本"1.72.0",
- Vulkan SDK 版本 1.1.85.0 在 Kubuntu 18.10 上链接
- 如何正确实现与基类不同的版本?
- 从预处理器获取 Windows 版本(C++ Win32)
- 表达式 SFINAE:如何根据类型是否包含具有一个或多个参数的函数来选择模板版本
- 如何在C++中将 Python 字符串转换为其转义版本?
- 不同版本的破坏者称为奇怪因素