Когда я компилирую даже простой код, используя особенность стандарта 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
для получения дополнительной информации … это дает некоторые подсказки, но я не знаю, куда идти отсюда.
Промежуточный (.ii
) в файлах кластера 1 отсутствуют некоторые строки, например (отрывок из 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.
Буду очень благодарен за любые подсказки или понимание.
Вы уже проделали всю необходимую работу для определения первопричины. Вы уже знаете ответ: вы опубликовали четкие различия между тем, как пользовательские установки gcc ведут себя на вашем «кластере 1» и «кластере 2», нерабочей и рабочей сборкой.
Итак, что-то явно отличается между этими двумя установками gcc; если один компилирует, связывает и запускает некоторый код, а другой задыхается от одного и того же куска кода. К сожалению, трудно точно определить, где все идет с рельсов. Создав сам gcc ранее, я могу сказать, что gcc — адски сложный и очень изменчивый пакет для установки. Например, после нескольких дней погони за таинственной ошибкой при связывании некоторого кода на C ++, я в итоге остановился на том, что gcc выбрал неправильную версию binutils в скрипте конфигурации gcc и внутренне отключил некоторые неясные функции, которые в конечном итоге проявились как ошибка соединения не gcc, а всего, что было создано с помощью gcc. Сам gcc был собран и установлен, без какой-либо жалобы, но он был сломан.
Таким образом, я нахожу совершенно неудивительным и вполне правдоподобным утверждение, что сам gcc был собран и установлен без явной проблемы, но он сломан и будет задыхаться от действительного кода таким образом.
Я полагаю, что ваша сборка gcc использует некорректный путь включения по умолчанию — он ищет заголовки в /usr/include
вместо собственного каталога установки. Это наиболее вероятный ответ, но это может быть что угодно.
Ну, у вас, очевидно, (как вы сами писали) два разных versoins gcc (один раз 4.4.7-3 и другой 4.4.7-4), и кажется, что они имеют (хотя и немного) различия в компиляции кода ,
Как я где-то читал, стандарт C ++ 11 еще не включен полностью во все компиляторы, так что, похоже, причина в одном кластере. Другой имеет (вы можете знать, почему) версию, в которую включено больше нового стандарта, и, поскольку вы хотите использовать именно эту функцию, я бы рекомендовал установить эту версию и на другом кластере.