未定义的符号:_ZN7QString13toUtf8_helperERKS_在运行时

时间:2014-12-31 00:11:25

标签: c++ eclipse qt gcc

我有两个使用Qt的项目。一个是用QtCreator开发的,另一个是用eclipse开发的。两者都使用相同的Qt 5.3.1库,两者都是用GCC编译的。但是,当我运行eclipse中的程序时,它会崩溃并显示消息Undefined symbol: _ZN7QString13toUtf8_helperERKS_

查找显示产生此错误的代码是

path.toStdString().c_str()     // path is a QString

并且qstring.h中的确切位置是

#if defined(Q_COMPILER_REF_QUALIFIERS) && !defined(QT_COMPILING_QSTRING_COMPAT_CPP)
    QByteArray toLatin1() const & Q_REQUIRED_RESULT
    { return toLatin1_helper(*this); }
    QByteArray toLatin1() && Q_REQUIRED_RESULT
    { return toLatin1_helper_inplace(*this); }
    QByteArray toUtf8() const & Q_REQUIRED_RESULT
    { return toUtf8_helper(*this); } //                 <- here
    QByteArray toUtf8() && Q_REQUIRED_RESULT
    { return toUtf8_helper(*this); }
    QByteArray toLocal8Bit() const & Q_REQUIRED_RESULT
    { return toLocal8Bit_helper(constData(), size()); }
    QByteArray toLocal8Bit() && Q_REQUIRED_RESULT
    { return toLocal8Bit_helper(constData(), size()); }

将另一个项目中的QString转换为std::string(QtCreator中的那个)可以正常工作。可能是什么问题? eclipse中是否缺少任何编译器选项?

修改 来自这两个项目的样本文件的编译器输出是(为了便于阅读,我添加了换行符):

的Eclipse

Building file: ../src/mysource1.cpp
Invoking: GCC C++ Compiler
g++ -I"/home/username/myfolder/myproject1/src"
    -I"/home/username/myfolder/myproject1/src/dialogs"
    -I"/home/username/myfolder/myproject1/src/ignore"
    -I/usr/local/Qt-5.3.1/include -I/usr/local/Qt-5.3.1/include/QtCore
    -I/usr/local/Qt-5.3.1/include/QtGui -I/usr/local/Qt-5.3.1/include/QtWidgets
    -O0 -g3 -Wall -c -fmessage-length=0 -std=c++0x -fPIE -MMD -MP
    -MF"src/mysource1.d" -MT"src/mysource1.d" -o "src/mysource1.o"
    "../src/mysource1.cpp"

QtCreator

g++ -c -pipe -g -Wall -W -D_REENTRANT -fPIE -DQT_WIDGETS_LIB -DQT_GUI_LIB
    -DQT_CORE_LIB -I/usr/local/Qt-5.3.1/mkspecs/linux-g++ -I../myproject2 
    -I../myproject2/src -I../myproject2/src/data -I../myproject2/src/dialogs 
    -I../myproject2/src/widgets -I../myproject2/src/widgets/overlays
    -I../myproject2/src/widgets/tools -I/usr/local/Qt-5.3.1/include
    -I/usr/local/Qt-5.3.1/include/QtWidgets -I/usr/local/Qt-5.3.1/include/QtGui
    -I/usr/local/Qt-5.3.1/include/QtCore -I. -I. -o mainwind.o
    ../myproject2/src/mainwind.cpp

EDIT2: 链接器输出如下:

的Eclipse

Invoking: GCC C++ Linker
g++ -L/usr/local/Qt-5.3.1/lib -o "myproject1" /*list of .o files*/
    -lQt5Core -lQt5Gui -lQt5Widgets -lgit2

QtCreator

g++ -Wl,-rpath,/usr/local/Qt-5.3.1/lib -o myproject2 /*list of .o files*/
    -L/usr/local/Qt-5.3.1/lib -lQt5Widgets -lQt5Gui -lQt5Core -lGL -lpthread

4 个答案:

答案 0 :(得分:7)

qmake/cmake是要走的路。但有趣的是看到链接器如何成功,然后在运行期间,我们得到一个未定义的引用(不是一个不匹配的DLL案例)。特别是因为QT github repotoUtf8_helper没有预处理器保护。再试一次。您是否可以添加-DQT_COMPILING_QSTRING_COMPAT_CPP这样,我们对#else部分中的toUtf8()采用略有不同的路径,而不是调用缺少的toUtf8_helper方法。

原因:我认为这是因为QtCore dll是使用一组预处理程序标志构建的,这些标记在项目构建期间未匹配。然后像代码中包含的qstring.h这样的头文件(具有内联函数)受到预处理器定义的保护,就像在toUtf8()期间调用的toStdString()一样,将采用不同的路径。

另请注意,建议不要像在此问题/答案中那样尝试使用qmake/cmake个文件来构建QT项目,并且必然会在项目中造成更多问题。

答案 1 :(得分:2)

Undefined symbol: _ZN7QString13toUtf8_helperERKS_可能由以下原因引起:

由于缺少-Wl,-rpath,/usr/local/Qt-5.3.1/libLD_LIBRARY_PATH,eclipse中的链接错误(过时的Qt库)。 Eclipse构建环境未设置为QtCreator构建环境。

您写道,您已使用ldd检查了应用的动态链接,但您也应在eclipse中添加缺少的链接器选项-Wl,-rpath,/usr/local/Qt-5.3.1/lib

(另一种方法是使用LD_LIBRARY_PATH,但保持两个构建环境相同是合理的.Ldd受LD_LIBRARY_PATH的影响,就像应用程序一样.LD_LIBRARY_PATH可能无法正确导出?)

还添加编译器标志-D_REENTRANT -fPIE -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I/usr/local/Qt-5.3.1/mkspecs/linux-g++

答案 2 :(得分:0)

我假设你想使用QString.toStdString()。c_str()函数将QString转换为const char *。这不是一种可行的方法。我不知道文件说的是什么,但我尝试使用此功能获取文件位置,这给了我一些奇怪的东西。请检查const char *是否与QString中的值相同。如果是这种情况,那么您有两种选择。

  1. 要么分两步完成。即QString().toStdString()和 在下一步中将其转换为const char*。虽然不是 干净,但它的工作原理。 (主要问题是要进行深层复制&#39;。当你 将QString转换为std :: string,Qt直接创建临时对象 尝试读取此临时对象。使用此方法,您将创建两个 分开的对象。
  2. 使用QString().toAscii.constData()QString():toUtf8().constData()(首选)

答案 3 :(得分:0)

从它的外观来看,你没有编译错误,而是链接错误。您还没有向我们展示正在使用的链接命令,您应该检查它们是否不同。要正确使用QString方法,您必须链接到QtCore。

您使用的是哪种构建系统?小心从命令行尝试?如果你自己编译怎么办?我看了你的一些评论,你好像用ldd检查了可执行文件,两者的输出是一样的吗?

另外,这些标志:-DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB,它们可能会有所不同,您应该尝试在Eclipse项目中定义这些标志。

如果你没有适当的构建系统(例如,你在Eclipse项目中缺少正确的定义),Qt的库可能很复杂而无法使用,特别是如果你打算使用QtQuick或者你打算在Android中构建Android未来。我会选择 qmake CMake 。如果您的计划是支持不同的IDE, CMake 是值得的,因为它可以为大多数IDE生成项目。