boost::filesystem::current_path() возвращает пустой путь

У меня есть программа на C++, где мне нужен текущий путь для последующего создания папки. Расположение моего исполняемого файла, скажем, /home/me/foo/bin. Это то, что я запускаю:

//Here I expect '/home/me/foo/bin/', but get ''
auto currentPath = boost::filesystem::current_path(); 

//Here I expect '/home/me/foo/', but get ''
auto parentPath = currentPath.parent_path();

//Here I expect '/home/me/foo/foo2/', but get 'foo2/'
string subFolder    = "foo2";
string folderPath   = parentPath.string() + "/" + subFolder + "/";

//Here I expect to create '/home/me/foo/foo2/', but get a core dump
boost::filesystem::path boostPath{ folderPath};
boost::filesystem::create_directories( boostPath); 

Я работаю на Ubuntu 16.04, используя Boost 1.66, установленный с менеджером пакетов Conan.

Раньше я успешно запускал это с предыдущей версией Boost (я полагаю, 1.45) без использования Conan. Boost был просто установлен на моей машине. Теперь я получаю дамп ядра при запуске create_directories( boostPath);.

Два вопроса:

  1. Почему current_path() не предоставляет мне фактический путь, а вместо этого возвращает и пустой путь?
  2. Даже если current_path() ничего не возвращает, почему у меня все еще есть дамп ядра, даже если я запускаю его с sudo? Разве я не мог бы просто создать папку (папки) в корне?

Изменить:

Запуск скомпилированной программы с некоторыми cout выводами вышеуказанных переменных между строками, а не с использованием режима отладки, обычно дает мне следующий вывод:

currentPath: ""
parentPath: ""
folderPath: /foo2/
Segmentation fault (core dumped)

Но иногда (примерно в 20% случаев) выдает следующий результат:

currentPath: "/"
parentPath: "/home/me/fooA�[oFw�[oFw@"
folderPath: /home/me/fooA�[oFw�[oFw@/foo2/
terminate called after throwing an instance of 'boost::filesystem::filesystem_error'
  what():  boost::filesystem::create_directories: Invalid argument
Aborted (core dumped)

Редактировать 2:

Запустив conan profile show default, я получаю:

[settings]
os=Linux
os_build=Linux
arch=x86_64
arch_build=x86_64
compiler=gcc
compiler.version=5
compiler.libcxx=libstdc++
build_type=Release
[options]
[build_requires]
[env]

person raggot    schedule 03.09.2018    source источник
comment
Вы убедились, что у вас нет проблем с доступом (разрешением)?   -  person A. Gille    schedule 03.09.2018
comment
@A.Gille, у меня действительно была такая проблема при отладке с помощью VS Code, и я исключил ее, используя sudo run и добавив несколько cout между строками для печати путей на консоли. Результаты были такими же.   -  person raggot    schedule 03.09.2018
comment
Под sudo run вы подразумеваете запуск скомпилированного исполняемого файла с помощью sudo? Попробуйте напрямую позвонить getcwd() и проверить errno, чтобы узнать, что может пойти не так.   -  person A. Gille    schedule 03.09.2018
comment
Убедитесь, что в отношении пакета conan ваши настройки conan install совпадают с настройками сборки. Например, профиль по умолчанию (.conan/profiles/defaul или conan profile show default) использует libcxx=libstdc++ из соображений обратной совместимости. Но ваш компилятор может использовать libcxx=libstdc++11 по умолчанию. Обычно это означает ошибки ссылок, а не время выполнения, но проверьте на всякий случай.   -  person drodri    schedule 03.09.2018
comment
@дродри, спасибо. Я добавил вывод conan profile show default к моему вопросу, и это действительно так, как вы догадались. Однако я не знаю, как проверить, что использует мой компилятор. Не могли бы вы дать мне ссылку, чтобы узнать, как его найти?   -  person raggot    schedule 03.09.2018
comment
@A.Gille, спасибо за предложение. Я включил в код несколько временных строк, следуя примеру реализации по этой ссылке. При таком подходе я нахожу правильный путь, home/me/foo/. На самом деле я ожидал home/me/foo/bin/, где находится мой скомпилированный код, но, по крайней мере, мы знаем, что я в правильном месте, и что current_path() дает мне совершенно неправильный результат.   -  person raggot    schedule 03.09.2018
comment
@drodri, я просматривал страницу Github надстройки 1.66. для Конана, и я понял, что никогда не настраивал профиль. Особенно отсутствие раздела [env] выглядит очень сильным кандидатом на то, чтобы быть моей проблемой. Попробую настроить правильно.   -  person raggot    schedule 03.09.2018
comment
@raggot в качестве быстрой проверки, я бы просто отредактировал профиль по умолчанию, написал libstdc++11 в качестве libcxx по умолчанию и попытался снова conan install ваши зависимости, а затем пересобрать ваше приложение. Обычно g++›5 будет использовать libstdc++11 в современных дистрибутивах. Старый компилятор и старые дистрибутивы будут использовать libstdc++.   -  person drodri    schedule 03.09.2018
comment
current_path сообщает вам рабочий каталог, который не обязательно является местоположением исполняемого файла.   -  person John Zwinck    schedule 03.09.2018
comment
@drodri, это сработало! Если вы уточните это в ответе, добавив несколько пояснительных строк, я буду рад принять это :)   -  person raggot    schedule 03.09.2018


Ответы (1)


Существует некоторое несоответствие между libcxx, используемым в зависимостях, и тем, который вы используете для сборки своего приложения.

В g++ (linux) есть 2 режима стандартной библиотеки, которые вы можете использовать: libstdc++, построенный без включения C++11, и libstdc++11, созданный с включенным C++11. Когда вы создаете исполняемый файл (приложение или общую библиотеку), все отдельные библиотеки, связанные вместе, должны быть связаны с одним и тем же libcxx.

  • libstdc++11 было установлено по умолчанию для g++ >= 5, но это также зависит от дистрибутива Linux. Бывает, что даже если вы устанавливаете g++>=5 в более старых дистрибутивах, таких как Ubuntu 14, по умолчанию libcxx все равно будет libstdc++, видимо, обновить его, не сломав, непросто. Также случается, что очень популярные службы CI, используемые в открытом исходном коде, такие как travis-ci, используют более старые дистрибутивы Linux, и поэтому libstdc++ связь была самой популярной.

  • libstdc++ было значением по умолчанию для g++ ‹ 5.

По историческим причинам и по причинам обратной совместимости профиль conan по умолчанию всегда использует libstdc++, даже для современных компиляторов в современных дистрибутивах. Вы можете прочитать свой профиль по умолчанию при первом запуске conan, а также найти его в виде файла в .conan/profiles/default или показать с помощью conan profile show default. Это, вероятно, изменится в conan 2.0 (или даже раньше), и правильный libcxx будет обнаружен для каждого компилятора, если это возможно.

Итак, если вы не меняете профиль по умолчанию (для производства рекомендуется использовать ваши собственные профили), то при выполнении conan install установленные зависимости строятся против libstdc++. Обратите внимание, что этот conan install в большинстве случаев не зависит от сборки, он просто загружает, распаковывает и настраивает нужные вам зависимости с запрошенной конфигурацией (из профиля по умолчанию).

Затем, когда вы строите, если вы не меняете _GLIBCXX_USE_CXX11_ABI, то вы можете использовать системный компилятор по умолчанию, в данном случае libstdc++11. В большинстве случаев появляется ошибка связывания, которая показывает это несоответствие. Но в вашем случае вам не повезло, и ваше приложение успело связать, но затем вылетело во время выполнения.

Есть несколько подходов к решению этой проблемы:

  • Также создайте свое приложение с помощью libstdc++. Убедитесь, что вы определили _GLIBCXX_USE_CXX11_ABI=0.
  • Установите свои зависимости для libstdc++11. Измените свой профиль по умолчанию, чтобы использовать libstdc++11, затем создайте новый conan install и перестройте приложение.
person drodri    schedule 03.09.2018
comment
Очень понятное объяснение. Теперь я лучше понимаю, что происходит в фоновом режиме и почему это не работает. Спасибо. - person raggot; 04.09.2018