0

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?

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Michael Labbé
  • 12,017
  • 4
  • 27
  • 36
  • What platform are you programming on? Are you programming against the glibc? – fuz Jun 14 '16 at 23:03
  • `_LARGEFILE_SOURCE` is obsolete anyways, why do you think you need it? Legacy code? – Baum mit Augen Jun 14 '16 at 23:04
  • @BaummitAugen It is not obsolete. If you compile a C program on i386 Linux, you get a 32 bit `off_t` by default. `_LARGEFILE_SOURCE` is kinda needed. – fuz Jun 14 '16 at 23:05
  • 2
    @FUZxxl It is obsolete if you just use `#define _FILE_OFFSET_BITS 64` instead. – Dietrich Epp Jun 14 '16 at 23:07
  • @DietrichEpp Which is a non-standard feature-test macro as opposed to the standard `_LARGEFILE_SOURCE`. – fuz Jun 14 '16 at 23:07
  • Cannot reproduce with g++6 on Arch btw. – Baum mit Augen Jun 14 '16 at 23:08
  • @BaummitAugen: You are probably compiling for 64-bit. – Dietrich Epp Jun 14 '16 at 23:09
  • @DietrichEpp Indeed, I was not aware that mattered. Thx. – Baum mit Augen Jun 14 '16 at 23:10
  • 2
    @FUZxxl `_FILE_OFFSET_BITS 64` is standard POSIX afaik, just like `_LARGEFILE_SOURCE`. Though the latter is called historical and *"New programs should not employ this macro; defining _XOPEN_SOURCE as just described or defining _FILE_OFFSET_BITS with the value 64 is the preferred mechanism to achieve the same result."* http://man7.org/linux/man-pages/man7/feature_test_macros.7.html – Baum mit Augen Jun 14 '16 at 23:12
  • Related to: http://stackoverflow.com/q/5378778/315052 – jxh Jun 14 '16 at 23:34
  • Names starting with underscore are implementation-specific and reserved for internal use. You must not use them unless explicitly allowed by the implementation. I doubt the documentation allows this. Also C and C++ are different languages. You would not expect `for c in "12345":` to be legal in C either. – too honest for this site Jun 14 '16 at 23:37

1 Answers1

6

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.

Dietrich Epp
  • 205,541
  • 37
  • 345
  • 415