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(); }
When compiled normally the result is 10
. When compiled with -O3 (inlining on) I get 11
.
I have clearly done an ODR violation for func()
.
It showed up when I started merging sources of different dll's into fewer dll's.
I have tried:
- GCC 5.1
-Wodr
(which requires-flto
) - gold linker with
-detect-odr-violations
- setting
ASAN_OPTIONS=detect_odr_violation=1
before running an instrumented binary with the address sanitizer.
Asan can supposedly catch other ODR violations (global vars with different types or something like that...)
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?
EDIT:
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.
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.
The tools are imperfect.
I think Gold's check will only notice when the symbols have different types or different sizes, which isn't true here (both functions will compile to the same number of instructions, just using a different immediate value).
I'm not sure why -Wodr
doesn't work here, but I think it only works for types, not functions, i.e. it will detect two conflicting definitions of a class type T
but not your func()
.
I don't know anything about ASan's ODR checking.
来源:https://stackoverflow.com/questions/31722473/is-there-a-way-to-detect-inline-function-odr-violations