Skip to content

AddressSanitizerOneDefinitionRuleViolation

Alexander Potapenko edited this page Aug 31, 2015 · 2 revisions

In short, One Definition Rule (ODR) requires that every object in C++ is defined just once.

==> odr0.cc <==
int XXX;
int main(){}

==> odr1.cc <==
long long XXX;

==> odr2.cc <==
float XXX;

Simple cases can be detected by linker:

% clang++ odr0.cc odr1.cc 
/tmp/odr1-f97b07.o:(.bss+0x0): multiple definition of `XXX'

In various other cases (e.g. when shared libraries are involved) the linker remains silent. AddressSanitizer, however, is able to detect most of the ODR violations at process startup.

Currently it requires a special run-time switch ASAN_OPTIONS=detect_odr_violation=1

% clang++ -fsanitize=address -fPIC -shared odr1.cc -o odr1.so
% clang++ -fsanitize=address odr0.cc odr1.so -Wl,-R.
% ASAN_OPTIONS=detect_odr_violation=1 ./a.out 
=================================================================
==19043==ERROR: AddressSanitizer: odr-violation (0x000001316280):
  [1] size=4 XXX odr0.cc
  [2] size=8 XXX odr1.cc

To find even more ODR violations (where the object sizes are equal) run with ASAN_OPTIONS=detect_odr_violation=2

% clang++ -fsanitize=address -fPIC -shared odr2.cc -o odr2.so
% clang++ -fsanitize=address odr0.cc odr2.so -Wl,-R.
% ASAN_OPTIONS=detect_odr_violation=1 ./a.out 
 <Silent>
% ASAN_OPTIONS=detect_odr_violation=2 ./a.out 
=================================================================
==19182==ERROR: AddressSanitizer: odr-violation (0x000001316280):
  [1] size=4 XXX odr0.cc
  [2] size=4 XXX odr2.cc
Clone this wiki locally