If the following code is compiled with gcc lfs.c -o lfs, it prints nothing. However, if it is compiled with g++ lfs.c -o lfs, it prints "_LARGEFILE_SOURCE defined by stdio.h!".
#ifdef _LARGEFILE_SOURCE
int largefile_defined_at_start = 1;
#else
int largefile_defined_at_start = 0;
#endif
// This defines _LARGEFILE_SOURCE, but only in C++!
#include <stdio.h>
int main(void) {
#ifdef _LARGEFILE_SOURCE
if (!largefile_defined_at_start)
printf("_LARGEFILE_SOURCE defined by stdio.h!");
#endif
return 0;
}
In either case, _LARGEFILE_SOURCE is not defined by the compiler:
gcc -dM -E - < /dev/null |grep _LARGEFILE_SOURCE |wc -l
0
g++ -dM -E - < /dev/null |grep _LARGEFILE_SOURCE |wc -l
0
Why is stdio.h defining _LARGEFILE_SOURCE when GCC is invoked via the g++ frontend?
Because g++ defines _GNU_SOURCE
, which basically implies all other feature macros, such as _LARGEFILE_SOURCE
. These additional macros are defined when the <features.h>
header is included, and most system header files include <features.h>
very early in the file. The fact that _GNU_SOURCE
is predefined is a continual source of frustration for people who want to write portable C++ code.
I believe you can simply:
#undef _GNU_SOURCE
However, this will break libstdc++. Ouch! What a pain! This all stems from one of the biggest design flaws in C++, which is the fact that #include
is basically textual inclusion. Since most of libstdc++ is defined (not just declared!) in header files, this means that they contaminate your program with _GNU_SOURCE
.
If you need to access an interface hidden by _GNU_SOURCE
(such as strerror_r
, for example, which is completely broken by _GNU_SOURCE
) then you can access those interfaces only from files which don't use any libstdc++ headers.
This is only a problem with libstdc++ as far as I know, so I think you can also avoid the problem by using libc++ or something else like that.