8

精简版

当我使用 C++11 标准的特性(函数)编译一个简单的代码时std::stod,GCC 4.9.1 失败并出现以下错误:

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));
                 ^

什么?

我使用的命令是g++ -std=c++11 example.cpp.

这是测试代码(在其他系统上编译得很好):

// 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;
}

细节

我使用的是 GCC 4.9.1 版本,我在运行 CentOS 6.5 的两个不同集群上编译自己(因为我不是管理员,所以我在我的主目录中的东西上使用模块系统)。

我将它们称为集群1和集群2:集群1是发生故障的地方。

GCC 以相同的方式和同时编译,并使用相同的模块文件加载(除了基本路径中的微小差异)。据我可以轻松检查,安装是相同的(两个集群上存在相同的包含文件,并且具有相同的内容)。

两个集群上的输出g++ -v相同(同样,安装路径除外):

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使用系统 GCC 在两个集群上给出相同的输出,除了在集群 1 上它说它是gcc version 4.4.7 20120313 (Red Hat 4.4.7-3) (GCC)并且在集群 2 上说gcc version 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC)

我正在尝试调试以g++ -std=c++11 -save-temps -MD example.cpp获取更多信息……这提供了一些线索,但我不知道从这里去哪里。

集群 1 上的中间 ( .ii) 文件缺少一些行,例如(文件摘录):diff.ii

< # 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;
---
> 
> 
>

正如我所解释的那样,两个集群上的 GCC 都试图包含类似的文件cwchar,但在集群1上,有空行而不是定义的东西。在集群2上,该stod函数位于中间文件中,但不在集群1上。

可能是预处理器错误?

现在查看.d(依赖)文件,我也看到了一个具体的区别。集群2中列出的一些文件未在集群1中列出。这是列表(我处理了.d文件的内容以说明不同的基本路径;//代表安装路径):

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

我很好奇是否cpp在所有错误的地方寻找包含,但这似乎是合法的(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.

这是一个非常令人沮丧的几个小时,试图追查问题的根源。当然,我可以使用类似的东西atof(myString.c_str())来代替std::stod,但我想知道是否存在一个潜在的问题会破坏使用 C++11 其他位的未来项目。

任何更多的线索或见解将不胜感激。

4

2 回答 2

4

您已经完成了所有必要的步骤来确定根本原因。您已经知道答案:您已经发布了自定义 gcc 安装在“集群 1”和“集群 2”(非工作和工作构建)上的行为方式之间的明显差异。

所以,这两个 gcc 安装之间有明显的不同;如果一个编译、链接和运行一些代码,而另一个阻塞在完全相同的代码段上。不幸的是,很难确定事情在哪里出轨。之前我自己构建了 gcc,我可以说 gcc 是一个非常困难且非常难以安装的包。例如,在链接一些 C++ 代码时追查了几天的神秘失败后,我最终追查到 gcc 在 gcc 的配置脚本中选择了错误版本的 binutils,并在内部关闭了一些晦涩的功能,最终表现为链接失败不是 gcc,而是用 gcc 构建的东西。gcc 本身被构建和安装,没有任何抱怨,但它被打破了。

因此,我认为 gcc 本身在没有明显问题的情况下构建和安装,但它已损坏,并且会以这种方式阻塞有效代码的命题,这完全不足为奇,而且完全合理。

我的猜测是你破坏的 gcc 构建使用了一个损坏的默认包含路径——它正在寻找头文件/usr/include,而不是你自己的自定义安装目录。这是最有可能的答案,但它真的可以是任何东西。

于 2014-09-27T18:07:40.460 回答
1

好吧,你显然有(就像你自己写的那样)两个不同的 gcc 版本(一个是 4.4.7-3,另一个是 4.4.7-4),而且它们在编译代码方面似乎有(尽管有细微差别) .

正如我在某处读到的,C++11 标准尚未完全包含在所有编译器中,所以这似乎是一个集群上的原因。另一个有(你可能知道为什么)一个包含更多新标准的版本,因为你希望你完全使用这个功能,我建议你在另一个集群上安装这个版本。

于 2014-10-01T19:11:57.553 回答