- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I have a software that has 2 versions of an implemented algorithm, so it used different versions of the same class (in my case its SSE vs AVX, but really, it's not relevant) in 2 different compiler units, and suprisingly the linker take the initiative of taking an arbitrary one.
Is it a bug (that I reproduced as well in Microsoft and GCC compiler) or a feature (if that so can someone help me finding where this behavior is specified) ?
Here is how to reproduce the problem:
toto.h
#include <stdio.h> #ifdef FLAG class foo { public: void bar() { printf("FLAG\n"); } }; #else class foo { public: void bar() { printf("NO FLAG\n"); } }; #endif #ifdef FLAG void call_foobar_FLAG() #else void call_foobar_NOFLAG() #endif { foo().bar(); }
toto_flag.cpp
#define FLAG #include "toto.h"
toto_noflag.cpp
#include "toto.h"
main.cpp
void call_foobar_FLAG();
void call_foobar_NOFLAG();
int main(int argc, char ** argv)
{
call_foobar_FLAG();
call_foobar_NOFLAG();
}
We should expect as output
FLAG NO FLAG
But we get
FLAG FLAG
or
NO FLAG NO FLAG
depending in which order object are linked...
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
FLAG may be #defined in (by) stdio.h
Also, you may have enabled pre-compiled headers.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Ok rename FLAG with RANDOM34834626723, <stdio.h> is here just for the printf to work in this reproductible example.
You would have the same result.
And no i did not enabled precompiled headers (nor optimizations, nor /Qip or /Qipo or global optimization or anything that could do some "magic" across objs)
Actually
gcc main.cpp toto_noflag.cpp toto_flag.cpp && a.exe
silently outputs NO FLAG twice
gcc main.cpp toto_flag.cpp toto_noflag.cpp && a.exe
silently outputs FLAG twice
So it's even not specific to Intel if this is a bug.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You are violating the ODR (One Definition Rule) so the implementation is allowed to do anything it wants.
See:
http://en.wikipedia.org/wiki/One_Definition_Rule
and section 3.2 of the C++ standard.
Judy
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you Judith, I understand now why what I did was completely non-standard.
I solved my issues by enclosing it in anonymous namespaces, which seems the proper way to do.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Judith,
This ODR raises another problem.
If I have a project mixing a file compiled with /QxAVX and another one with any other architecture selection (for instance /QxSSE), if both for instance use a STL class like std::basic_string. Then in both translation unit will share the same std::basic_string and have AVX code into it.
And unfortunately in Intel Compiler there is no flag to activate AVX (in the way that the instrinsic are translated into VEX instructions) without having these injection of AVX code where its not needed (and which prevents the use of classes, that I cannot put in an anonymous namespace, between compilands targeted for different architectures).
Best Regards,
Emmanuel

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page