有没有办法检测内联函数ODR违规?

时间:2015-07-30 11:24:13

标签: 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(); }

正常编译时,结果为10。当使用-O3(内联)编译时,我得到11

我已明确对func()进行了ODR违规。

当我开始将不同dll的来源合并为更少的dll时,它就出现了。

我试过了:

  • GCC 5.1 -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){} };

在此之后有大量复制/粘贴+小修改的遗留代码是一种乐趣。

2 个答案:

答案 0 :(得分:5)

工具不完善。

我认为Gold的检查只会在符号具有不同类型或不同大小时才会发现,这里不是真的(两个函数都会编译为相同数量的指令,只是使用不同的立即值)。

我不确定为什么-Wodr在这里不起作用,但我认为它只适用于类型,而不是函数,即它会检测类类型{{1}的两个冲突定义但不是你的T

我对ASO的ODR检查一无所知。

答案 1 :(得分:3)

检测此类问题的最简单方法是将所有函数复制到单个编译单元中(如果需要,可临时创建一个)。然后,任何C ++编译器都能够在编译该文件时检测并报告重复的定义。