onq*_*tam 14 c++ linker g++ linker-errors one-definition-rule
所以我在2个单独的翻译单元中有这个代码:
// a.cpp
#include <stdio.h>
inline int func() { return 5; }
int proxy();
int main() { printf("%d", func() + proxy()); }
// b.cpp
inline int func() { return 6; }
int proxy() { return func(); }
Run Code Online (Sandbox Code Playgroud)
正常编译时,结果是10
.当使用-O3(内联)编译时,我得到了11
.
我已经明确做了ODR违规func()
.
当我开始将不同dll的来源合并为更少的dll时,它就出现了.
我试过了:
-Wodr
(需要-flto
)-detect-odr-violations
ASAN_OPTIONS=detect_odr_violation=1
在使用地址清理程序运行检测二进制文件之前进行设置.据称,Asan可以捕获其他ODR违规行为(具有不同类型或类似内容的全球变量......)
这是一个非常令人讨厌的C++问题,我很惊讶没有可靠的工具来检测它.
也许我误用了我试过的一种工具?或者是否有不同的工具?
编辑:
即使我使两个实现完全func()
不同,这个问题仍然没有引起注意,因此它们不会被编译为相同数量的指令.
这也会影响类体内定义的类方法 - 它们是隐式内联的.
// a.cpp
struct A { int data; A() : data(5){} };
// b.cpp
struct A { int data; A() : data(6){} };
Run Code Online (Sandbox Code Playgroud)
遗留代码后有很多复制/粘贴+小修改,这是一种乐趣.
这些工具并不完美.
我认为Gold的检查仅在符号具有不同类型或不同大小时才会注意到,这在这里是不正确的(两个函数将编译为相同数量的指令,仅使用不同的立即值).
我不确定为什么-Wodr
在这里不起作用,但我认为它只适用于类型,而不是函数,即它将检测类类型的两个冲突定义,T
但不会检测func()
.
我对ASan的ODR检查一无所知.
检测此类问题的最简单方法是将所有函数复制到一个编译单元中(如果需要,可以临时创建一个)。任何 C++ 编译器都可以在编译该文件时检测并报告重复的定义。