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.
inline
functions in a .cpp file would be. I can't think of any possible advantage. – Backwaterstruct A { A(){} };
- here the constructor is defined inside the struct definition and is implicitly inline. 2 such structs may have identical layout but different inline methods... – Breseeinline
specifiers from functions defined in .cpp files and examine any resulting linkage errors. – Backwater