Search code examples
c++cgcclarge-fileslarge-file-support

Why is _LARGEFILE_SOURCE defined in stdio.h when compiling with g++ but not gcc?


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?


Solution

  • 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.