有没有办法检测内联函数 ODR 违规?
所以我在 2 个独立的翻译单元中有这段代码:
So I have this code in 2 separate translation units:
// 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(); }
正常编译时结果为10
.当使用 -O3(内联)编译时,我得到 11
.
When compiled normally the result is 10
. When compiled with -O3 (inlining on) I get 11
.
我显然对 func()
做了 ODR 违规.
I have clearly done an ODR violation for func()
.
当我开始将不同 dll 的源合并为更少的 dll 时,它就出现了.
It showed up when I started merging sources of different dll's into fewer dll's.
我试过了:
- GCC 5.1
-Wodr
(需要-flto
) - 带有
-detect-odr-violations
的黄金链接器 - 在使用地址清理程序运行检测二进制文件之前设置
ASAN_OPTIONS=detect_odr_violation=1
.
据称,Asan 可以捕获其他 ODR 违规行为(具有不同类型的全局变量或类似的东西......)
Asan can supposedly catch other ODR violations (global vars with different types or something like that...)
这是一个非常讨厌的 C++ 问题,我惊讶没有可靠的工具来检测它.
This is a really nasty C++ issue and I am amazed there isn't reliable tooling for detecting it.
也许我误用了我尝试过的工具之一?或者有什么不同的工具可以做到这一点?
Pherhaps I have misused one of the tools I tried? Or is there a different tool for this?
编辑:
即使我使 func()
的 2 个实现完全不同,因此问题仍然没有被注意到,因此它们不会被编译成相同数量的指令.
The problem remains unnoticed even when I make the 2 implementations of func()
drastically different so they don't get compiled to the same amount of instructions.
这也会影响类体内定义的类方法 - 它们是隐式内联的.
This also affects class methods defined inside the class body - they are implicitly inline.
// a.cpp
struct A { int data; A() : data(5){} };
// b.cpp
struct A { int data; A() : data(6){} };
带有大量复制/粘贴 + 小修改的遗留代码是一种乐趣.
Legacy code with lots of copy/paste + minor modifications after that is a joy.
推荐答案
检测此类问题的最简单方法是将所有函数复制到单个编译单元中(如果需要,临时创建一个).然后,任何 C++ 编译器都能够在编译该文件时检测并报告重复定义.
The simplest way to detect such concerns is to copy all the functions into a single compilation unit (create one temporarily if needed). Any C++ compiler will then be able to detect and report duplicate definitions when compiling that file.
相关文章