【问题标题】:Compiler error with yaml-cpp - undefined reference to `YAML::detail::node_data::convert_to_map`yaml-cpp 的编译器错误 - 未定义对 `YAML::detail::node_data::convert_to_map` 的引用
【发布时间】:2023-03-05 09:39:01
【问题描述】:

这是完整的日志:

/tmp/ccCvErNZ.o: In function `YAML::detail::node& YAML::detail::node_data::get<std::string>(std::string const&, std::shared_ptr<YAML::detail::memory_holder>)':
cricket.cpp:(.text._ZN4YAML6detail9node_data3getISsEERNS0_4nodeERKT_St10shared_ptrINS0_13memory_holderEE[_ZN4YAML6detail9node_data3getISsEERNS0_4nodeERKT_St10shared_ptrINS0_13memory_holderEE]+0x94): undefined reference to `YAML::detail::node_data::convert_to_map(std::shared_ptr<YAML::detail::memory_holder>)'
collect2: error: ld returned 1 exit status

我要编译的代码很简单

#include <iostream>
#include <yaml-cpp/yaml.h>

using namespace std;

int main() {
    YAML::Node test = YAML::LoadFile("test.yaml");
    if (test["date"]) {
      cout << "HELLO";
    }

    return 0;
}

我使用的 YAML 是来自 http://www.yaml.org/start.html 的示例

如果我只是尝试加载 YAML,它可以正常加载。但是,如果我尝试访问任何数据,我会得到同样的错误。所以这不是链接问题。

编辑:我可以执行 cout &lt;&lt; testcout &lt;&lt; test.type() 之类的操作以及其他功能。我认为问题在于使用基于字符串的映射来访问内部节点。

【问题讨论】:

  • 这不是完整的日志,这只是错误消息。您有一个链接错误,因此您需要向我们展示失败的链接命令。错误来自于 g++ ... 命令。将其发布在您的问题正文中。
  • @Mike Kinghan`在函数YAML::detail::node&amp; YAML::detail::node_data::get&lt;std::string&gt;(std::string const&amp;, boost::shared_ptr&lt;YAML::detail::memory_holder&gt;)': /usr/include/yaml-cpp/node/detail/impl.h:89: undefined reference to YAML::detail::node_data::convert_to_map(boost::shared_ptr<:detail::memory_holder>)'`
  • @MikeKinghan 不幸的是我无法编辑帖子,因为它不是我的帖子,但我的 cmake 文件位于本页末尾的 cmets 中......

标签: c++ yaml undefined-reference yaml-cpp


【解决方案1】:

就我而言,我在两台计算机上运行完全相同的代码,但只在其中一台计算机上出现错误,这几乎让我发疯。这不是编译错误,链接错误什么的,我认为代码是脏的什么的。

我尝试了所有选项:

  1. 从源代码定期构建并使用cmake .. => make => make install 安装
  2. 同1,CC=$(which gcc) CXX=$(which g++) cmake -DBUILD_SHARED_LIBS=ON ..
  3. 从 apt 中卸载默认包(我使用的是 ubuntu 16.04)

一切都失败了,直到我找到 Ilya Golshtein 的答案,然后在我将使用 yaml-cpp 的代码中,我在 YAML::LoadFIle Line 之前添加了这段代码 jsut

    YAML::BadConversion::~BadConversion()
{
}

void  YAML::detail::node_data::convert_to_map(std::shared_ptr<YAML::detail::memory_holder>)
{
}

这是唯一有效的解决方案

【讨论】:

    【解决方案2】:

    我确认 yaml-cpp 库的某些版本包含此问题(与不正确的链接无关)。 它很脏,但我已经通过在我的代码中定义空函数来解决它,它看起来像

        YAML::BadConversion::~BadConversion()
        {
        }
    
        void  YAML::detail::node_data::convert_to_map(std::shared_ptr<YAML::detail::memory_holder>)
        {
        }
    

    该方法并不完美(例如,因为如果使用另一个库版本会导致重复)。

    【讨论】:

      【解决方案3】:

      您似乎没有正确链接yaml-cpp 库。编译时添加参数-lyaml-cpp。例如:

      g++ -I/usr/local/include -L/usr/local/lib -lyaml-cpp -o test main.cpp
      

      编辑

      另一种选择是将此 cmake 包含到您的 CMakeLists.txt 中:

      # attempt to find static library first if this is set
      if(YAMLCPP_STATIC_LIBRARY)
          set(YAMLCPP_STATIC libyaml-cpp.a)
      endif()
      
      # find the yaml-cpp include directory
      find_path(YAMLCPP_INCLUDE_DIR yaml-cpp/yaml.h
                PATH_SUFFIXES include
                PATHS
                ~/Library/Frameworks/yaml-cpp/include/
                /Library/Frameworks/yaml-cpp/include/
                /usr/local/include/
                /usr/include/
                /sw/yaml-cpp/         # Fink
                /opt/local/yaml-cpp/  # DarwinPorts
                /opt/csw/yaml-cpp/    # Blastwave
                /opt/yaml-cpp/
                ${YAMLCPP_DIR}/include/)
      
      # find the yaml-cpp library
      find_library(YAMLCPP_LIBRARY
                   NAMES ${YAMLCPP_STATIC} yaml-cpp
                   PATH_SUFFIXES lib64 lib
                   PATHS ~/Library/Frameworks
                          /Library/Frameworks
                          /usr/local
                          /usr
                          /sw
                          /opt/local
                          /opt/csw
                          /opt
                          ${YAMLCPP_DIR}/lib)
      
      # handle the QUIETLY and REQUIRED arguments and set YAMLCPP_FOUND to TRUE if all listed variables are TRUE
      include(FindPackageHandleStandardArgs)
      FIND_PACKAGE_HANDLE_STANDARD_ARGS(YAMLCPP DEFAULT_MSG YAMLCPP_INCLUDE_DIR YAMLCPP_LIBRARY)
      mark_as_advanced(YAMLCPP_INCLUDE_DIR YAMLCPP_LIBRARY)
      

      【讨论】:

      【解决方案4】:

      确保这两个文件存在:

      /usr/local/lib/libyaml-cpp.a
      /usr/local/include/yaml-cpp/yaml.h
      

      我的 CMakeLists.txt:

      CMAKE_MINIMUM_REQUIRED(VERSION 3.4)
      FIND_PACKAGE(yaml-cpp REQUIRED)
      ADD_EXECUTABLE(yaml_cpp_test yaml_cpp_test.cpp)
      TARGET_LINK_LIBRARIES(yaml_cpp_test yaml-cpp)
      

      yaml_cpp_test.cpp 的内容与问题中提到的相同。


      我尝试在 vps (Ubuntu 14.04.1 LTS) 上重现问题

      wget -c https://github.com/jbeder/yaml-cpp/archive/release-0.5.1.tar.gz
      tar xvf release-0.5.1.tar.gz yaml-cpp-release-0.5.1/
      cd yaml-cpp-release-0.5.1/
      sudo apt-get install cmake
      sudo apt-get install libboost-dev
      cmake .
      make
      make install
      

      之后,yaml-cpp 安装到 /usr/local/lib 和 /usr/local/include
      我的工作目录中的文件:

      fqlgy@li407-86:~/yaml-cpp$ ll
      total 12
      -rw-r--r-- 1 fqlgy fqlgy 162 May  8 03:29 CMakeLists.txt
      -rw-r--r-- 1 fqlgy fqlgy  10 May  8 03:11 test.yaml
      -rw-r--r-- 1 fqlgy fqlgy 240 May  8 03:11 yaml_cpp_test.cpp
      

      当我尝试运行“cmake .”时,出现了一些错误,所以我删除了CMakeFiles/CMakeOutput.log这一行,CMakeLists.txt 的内容是:

      CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
      ADD_EXECUTABLE(yaml_cpp_test yaml_cpp_test.cpp)
      TARGET_LINK_LIBRARIES(yaml_cpp_test yaml-cpp)
      

      以下输出符合预期:

      fqlgy@li407-86:~/yaml-cpp$ cmake .
      -- Configuring done
      -- Generating done
      -- Build files have been written to: /home/fqlgy/yaml-cpp
      fqlgy@li407-86:~/yaml-cpp$ make
      Scanning dependencies of target yaml_cpp_test
      [100%] Building CXX object CMakeFiles/yaml_cpp_test.dir/yaml_cpp_test.cpp.o
      Linking CXX executable yaml_cpp_test
      [100%] Built target yaml_cpp_test
      fqlgy@li407-86:~/yaml-cpp$ ./yaml_cpp_test
      HELLO
      

      【讨论】:

      • 我做了完全相同的事情,但仍然出现同样的错误......这太疯狂了!
      • In function YAML::detail::node& YAML::detail::node_data::get<:string>(std::string const&, boost::shared_ptr<:detail ::memory_holder>)': yaml_example.cpp:(.text._ZN4YAML6detail9node_data3getISsEERNS0_4nodeERKT_N5boost10shared_ptrINS0_13memory_holderEEE[_ZN4YAML6detail9node_data3getISsEERNS0_4nodeERKT_N5boost10shared_ptrINS0_13memory_holderEEE]+0xae)
      • 您可以尝试运行“nm /usr/local/lib/libyaml-cpp.a |grep convert_to_map”来检查符号吗?
      • 0000000000001670 T _ZN4YAML6detail9node_data14convert_to_mapEN5boost10shared_ptrINS0_13memory_holderEEE 0000000000000060 r _ZZN4YAML6detail9node_data14convert_to_mapEN5boost10shared_ptrINS0_13memory_holderEEEE19__PRETTY_FUNCTION__
      • 可以从源代码构建。我将在相同的操作系统版本上尝试它,稍后再给您反馈。
      【解决方案5】:

      我在 Debian 系统上尝试编译 OpenXcom 时遇到了类似的情况。事实证明,我混合使用了测试包和稳定包,yaml 包来自稳定包,如果有多个初始函数,这种组合会以某种方式导致链接失败。

      如果这是您遇到的情况(并且您也在使用 Debian),请尝试从 stable 编译源包

      apt-get --build source libyaml-cpp0.5/stable
      

      此命令将为 libyaml 构建 .deb 包,然后您可以使用 dpkg 插入它们,如下所示:

      dpkg -i libyaml-cpp0.5*.deb
      

      作为根。

      从源代码编译 libyaml 将使其链接到您已经拥有的测试库,而不是期望稳定的库,因此应该可以解决上述问题。至少对我有用。

      即使您不使用 Debian,从源代码(例如 tarball)编译 yaml-cpp 也可能出于类似原因。

      【讨论】:

      • 你是什么意思然后用dpkg插入
      • 使用 dpkg -i 安装编译过程创建的包。我已经详细说明了如何做到这一点。
      • 我需要对当前的 yaml-cpp 做 dpkg remove 吗?
      • 如果你当前的 yaml-cpp 已经是 0.5,那没关系,因为它应该只是用新的替换旧的。但是,我不能完全确定,所以删除当前的只是为了确定它是否不太麻烦。
      • 我完成了以上所有操作,直到出现相同的链接错误!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多