2

I'm creating a library that will need different command-line defined macros (-D option) per resulting binary (.exe, .so, .dll) that uses it. I would like to ensure each translation unit that will be a part of resulting binary, was compiled with the same macro definition. This is to e.g. prevent accidental ODR violations and other unexpected behavior.

For instance, this should be prevented:

g++ -DMY_MACRO=5 a.cpp
g++ -DMY_MACRO=7 b.cpp
ld a.o b.o -o result

The library will provide header - library.hpp - that will be included in all translation units using it. My idea is to use that header as a place to create checks for misuse.

The question is, what's the best way to do it?

Preferably misuse would be detected, in order of preference, during:

  • compilation
  • linking
  • runtime

It's likely not possible during compilation due to way how C/C++ compilers work. But maybe at least during linking?

I would like to avoid using external tools/scripts. I know one could write a script that goes through all object files and checks if all used the same value. But maybe there is a way less intrusive for the buildsystem, just reusing how C++ linker or compiler works.

Platform independent solution would be best, but ways for doing it independently for gcc/clang and msvc would also be useful.

Macro definition will always be an integral number.

stoper
  • 131
  • 1
  • 9
  • 1
    How about something along these lines: main.cpp: int checkMyMacro#MY_MACRO; a.cpp and b.cpp: static int *checkMyMacro = &checkMyMacro#MY_MACRO; resulting in a unresolved external error from linker on misuse. – Matthias Mar 21 '18 at 07:44
  • @Matthias Haven't thought of that. This solution is close to perfect, only drawback is having to force users to add at least one line in their code, but good thing is this is enforced by linker. Still this may be good enough for my application :) – stoper Mar 21 '18 at 22:42

2 Answers2

1

How about something along these lines:

main.cpp:

int checkMyMacro#MY_MACRO;

a.cpp and b.cpp:

static int *checkMyMacro = &checkMyMacro#MY_MACRO;

resulting in a unresolved external error from linker on misuse.

You could insert the second part into the header defining that macro.

Matthias
  • 1,251
  • 8
  • 16
-2

If you merely wish to protect against accidental misuse something like the following would likely be enough:

#if defined(MY_MACRO) && MY_MACRO_MIN > MY_MACRO || MY_MACRO_MAX < MY_MACRO
#error MY_MACRO is out of range
#endif

Protecting against malicious misuse at any point prior to run-time is basically impossible under the circumstances you describe.

Guillaume Racicot
  • 32,627
  • 7
  • 60
  • 103
SoronelHaetir
  • 11,346
  • 1
  • 8
  • 18
  • The problem is not about protecting against wrong value, but rather preventing someone using different values in two .cpp files. – stoper Jan 05 '18 at 20:23