Итак, у меня есть этот код в двух отдельных единицах перевода:
// 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
.
Я явно нарушил ODR для func()
.
Это появилось, когда я начал объединять источники разных 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){} };
Устаревший код с большим количеством копий/вставок + незначительные модификации после этого - это радость.
inline
в файле .cpp. Я не могу думать ни о каком возможном преимуществе. - person sjdowling   schedule 30.07.2015struct A { A(){} };
- здесь конструктор определен внутри определения структуры и неявно встроен. 2 такие структуры могут иметь одинаковый макет, но разные встроенные методы... - person onqtam   schedule 30.07.2015inline
из функций, определенных в файлах .cpp, и изучить все возникшие ошибки компоновки. - person sjdowling   schedule 30.07.2015