Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

g++ does not include files it says it includes for C++11?

Short version

When I compile even a simple code using a feature of the C++11 standard (the std::stod function), GCC 4.9.1 fails with the following error:

example.cpp: In function 'int main()':
example.cpp:10:18: error: 'stod' is not a member of 'std'
   double earth = std::stod (orbits,&sz);
                  ^
example.cpp:11:17: error: 'stod' is not a member of 'std'
   double moon = std::stod (orbits.substr(sz));
                 ^

What?

The command I use is g++ -std=c++11 example.cpp.

This is the test code (which compiles fine on other systems):

// stod example from http://www.cplusplus.com/reference/string/stod/
#include <iostream>   // std::cout
#include <string>     // std::string, std::stod

int main ()
{
  std::string orbits ("365.24 29.53");
  std::string::size_type sz;     // alias of size_t

  double earth = std::stod (orbits,&sz);
  double moon = std::stod (orbits.substr(sz));
  std::cout << "The moon completes " << (earth/moon) << " orbits per Earth year.\n";
  return 0;
}

details

I am using a version of GCC 4.9.1 I compiled myself on two different clusters running CentOS 6.5 (I use the modules system on stuff in my home dir since I'm not an admin).

I will call them cluster 1 and cluster 2: cluster 1 is where the failure happens.

The GCCs were compiled in the same way and at the same time, and loaded using identical module files (save for a minor difference in the base path). The installations are, as far as I can easily check, identical (the same include files exist on both clusters, and have the same contents).

The output from g++ -v is the same on both clusters (again, except for the install path):

Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/home/andyras/bin/gcc-4.9.1/libexec/gcc/x86_64-unknown-linux-gnu/4.9.1/lto-wrapper
Target: x86_64-unknown-linux-gnu
Configured with: ../gcc-4.9.1/configure --prefix=/home/andyras/bin/gcc-4.9.1 --enable-languages=c,c++,fortran
Thread model: posix
gcc version 4.9.1 (GCC)

g++ -v using the system GCC gives the same output on both clusters, except on cluster 1 it says it is gcc version 4.4.7 20120313 (Red Hat 4.4.7-3) (GCC) and on cluster 2 says gcc version 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC)

I am trying to debug using g++ -std=c++11 -save-temps -MD example.cpp for more info... this gives some clues, but I don't know where to go from here.

The intermediate (.ii) files on cluster 1 are missing some lines, for example (excerpt from diffing the .ii files):

< # 277 "/opt/gcc-4.9.1/include/c++/4.9.1/cwchar" 3
---
> # 277 "/home/andyras/bin/gcc-4.9.1/include/c++/4.9.1/cwchar" 3
961,963c934,936
<   using std::wcstold;
<   using std::wcstoll;
<   using std::wcstoull;
---
> 
> 
>

As I interpret it, GCC on both clusters tries to include files like cwchar, but on cluster 1 there are blank lines instead of things being defined. On cluster 2 the stod function is in the intermediate file, but not on cluster 1.

Could it be a preprocessor error?

Now looking at the .d (dependency) files, I also see a concrete difference. There are some files listed on cluster 2 that are not listed on cluster 1. Here is the list (I processed the contents of the .d files to account for the different base paths; // stands in for the install path):

85a86,108
> //gcc-4.9.1/include/c++/4.9.1/ext/string_conversions.h
> //gcc-4.9.1/include/c++/4.9.1/cstdlib
> /usr/include/stdlib.h
> /usr/include/bits/waitflags.h
> /usr/include/bits/waitstatus.h
> /usr/include/sys/types.h
> /usr/include/sys/select.h
> /usr/include/bits/select.h
> /usr/include/bits/sigset.h
> /usr/include/sys/sysmacros.h
> /usr/include/alloca.h
> //gcc-4.9.1/include/c++/4.9.1/cstdio
> /usr/include/libio.h
> /usr/include/_G_config.h
> /usr/include/bits/stdio_lim.h
> /usr/include/bits/sys_errlist.h
> //gcc-4.9.1/include/c++/4.9.1/cerrno
> /usr/include/errno.h
> /usr/include/bits/errno.h
> /usr/include/linux/errno.h
> /usr/include/asm/errno.h
> /usr/include/asm-generic/errno.h
> /usr/include/asm-generic/errno-base.h

I was curious if cpp was looking for includes in all the wrong places, but this seems legit (cpp -v):

#include <...> search starts here:
 /home/andyras/bin/gcc-4.9.1/include
 /home/andyras/bin/gcc-4.9.1/include/c++/4.9.1/
 /home/andyras/bin/gcc-4.9.1/include/c++/4.9.1/x86_64-unknown-linux-gnu/
 /home/andyras/bin/gcc-4.9.1/lib/gcc/x86_64-unknown-linux-gnu/4.9.1/include
 /usr/local/include
 /home/andyras/bin/gcc-4.9.1/lib/gcc/x86_64-unknown-linux-gnu/4.9.1/include-fixed
 /usr/include
End of search list.

This has been a very frustrating couple of hours trying to track down the source of the problem. I could, of course, use something like atof(myString.c_str()) instead of std::stod, but I am wondering if there is an underlying issue that will foul up future projects using other bits of C++11.

Any more clues or insight would be very much appreciated.

like image 700
andyras Avatar asked Sep 23 '14 23:09

andyras


2 Answers

You have already done all the necessary footwork to determine the root cause. You already know the answer: you have posted clear differences between how custom gcc installs behave on your "cluster 1" and "cluster 2", a non-working and a working build.

So, something is obviously different between these two gcc installs; if one compiles, links, and runs some code, and the other one chokes on the exact same piece of code. Unfortunately, it's hard to pinpoint where things go off the rails. Having built gcc myself before, previously, I can say that gcc is a hellishly difficult, and very fickle package to install. For example, after several days chasing a mysterious failure when linking some C++ code, I ended up chasing it down to gcc picking up the wrong version of binutils, in gcc's configure script, and internally turning off some obscure feature, that eventually manifested itself as a link failure not of gcc, but of stuff that got built with gcc. gcc itself got built, and installed, with nary a complaint, but it was broken.

So, I find it completely unsurprising, and entirely plausible, the proposition that gcc itself got built and installed without an apparent issue, but it's broken, and will choke on valid code, in this fashion.

My guess would be that your busted gcc build is using a broken default include path -- it's looking for headers in /usr/include, instead of your own custom installation directory. That's the most likely answer, but it could really be anything.

like image 92
Sam Varshavchik Avatar answered Nov 12 '22 15:11

Sam Varshavchik


Well, you obviously have (like you wrote yourself) two different versoins of gcc (one time 4.4.7-3 and the other 4.4.7-4), and It seems that they have (even though slightly) differences in compiling the code.

As I've read somewhere, the C++11-standard is not yet included completely in all compilers, so this seems to be the cause on the one Cluster. The other has (you might know why) a version where more of the new standard is included and since you want you use exactly this feature I'd recommend installing this version on the other Cluster too.

like image 32
fkarg Avatar answered Nov 12 '22 16:11

fkarg