有没有办法检测内联函数 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.

相关文章