Così ho questo codice in 2 unità di traduzione distinte:C'è un modo per rilevare le violazioni ODR della funzione inline?
// 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(); }
Quando compilato normalmente il risultato è 10
. Quando compilato con -O3 (inlining on) ottengo 11
.
Ho chiaramente eseguito una violazione ODR per func()
.
Si è presentato quando ho iniziato a unire fonti di dll diverse in meno dll.
ho provato:
- GCC 5.1
-Wodr
(che richiede-flto
) - linker oro con
-detect-odr-violations
- modificando
ASAN_OPTIONS=detect_odr_violation=1
prima di eseguire un binario strumentato con l'indirizzo disinfettante.
Asan può presumibilmente prendere altre violazioni ODR (vars globali con diversi tipi o qualcosa del genere ...)
Questo è un problema veramente brutto C++ e io sono stupito Non c'è attrezzatura affidabile per averlo rilevato.
Forse ho abusato di uno degli strumenti che ho provato? O c'è uno strumento diverso per questo?
EDIT:
Il problema resta inosservato anche quando faccio le 2 implementazioni di func()
drasticamente diverso in modo che non vengono compilati per la stessa quantità di istruzioni.
Questo influisce anche sui metodi di classe definiti all'interno del corpo della classe: sono implicitamente incorporati.
// a.cpp
struct A { int data; A() : data(5){} };
// b.cpp
struct A { int data; A() : data(6){} };
Codice precedente con un sacco di copia/incolla + piccole modifiche dopo che è una gioia.
Mi chiedo quale sarebbe il caso d'uso per avere funzioni 'inline' in un file .cpp. Non riesco a pensare a nessun vantaggio possibile. – sjdowling
@sjdowling perché la parola chiave inline? codice legacy. Considerate anche questo: '' 'struct A {A() {}};' '' - qui il costruttore è definito all'interno della definizione struct ed è implicitamente in linea. 2 tali strutture possono avere lo stesso layout ma diversi metodi in linea ... – onqtam
Forse il modo più semplice per trovare queste violazioni ODR in questo codice legacy è rimuovere tutti gli specificatori 'in linea' dalle funzioni definite nei file .cpp ed esaminare eventuali errori di collegamento risultanti. – sjdowling