【问题标题】:Strange type of "multiple definition of" error奇怪类型的“多重定义”错误
【发布时间】:2017-06-02 13:05:14
【问题描述】:

我正在使用 Qt/MinGW/Windows 进行一个大型项目。最近我把我的一些源文件的地方改了,重新编译,经过一些修正,开始收到这样的消息

(.idata$5+0x0):-1: error: multiple definition of `_imp___ZN9QwtThermo16staticMetaObjectE'

这发生在两个类中:QwtThermo 和 QwtPlotPicker 在以前没有此类错误的代码中(请记住:我只是将基本文件夹中文件的位置更改为一些子文件夹;没有更改代码(据我记得) 并注意许多其他 Qwt 类也包括在内,并且通常在没有任何编译错误的情况下使用;这是唯一给我带来问题的两个)。

现在“多重定义”是 C++ 中的一个常见错误,我已经知道通常如何解决它(包括 StackOverflow 在内的许多线程都在谈论它):一个人应该只在头文件中声明内容,同时在头文件中定义它们.cpp 文件。

不幸的是,这一次似乎不是一个可行的解决方案。这是发生了什么:

  • 我对包含此标头的位置进行了研究,但没有发现任何问题。我很伤心,它以前编译得很好。
  • 如果我创建了 QwtPlotPicker 的子类(我是否使用它无关紧要),问题只会出现在 QwtPlotPicker 上。如果我只在头文件中声明子类的名称并在.cpp中定义它,那么我可以编译,但是一旦我开始使用它(在头文件中声明了一个成员指针),然后编译出现错误“'vtable for Picker'的未定义引用”。所以在头文件中声明类并在 .cpp 中定义它实际上并没有帮助;
  • 使用 QwtThermo,如果我在头文件中包含文件并且只声明指向它的指针(无子类),则错误已经开始出现。如果我只在项目的标头中声明 QwtThermo 类并在 .cpp 文件中包含 QwtThermo 自己的标头,则可以解决此问题;这样我就可以声明一个指向它的成员指针,并在它的父类中的 .cpp 文件中用“new”实例化指针,但是一旦我通过调用它的方法开始使用它,“多重定义" 再次开始出现。

如您所见,这一次似乎不仅仅是“在标头中声明并在 .cpp 中定义”的问题;更多的事情正在发生。 :T

那么可能出了什么问题?抱歉没有发布任何代码,但请相信我已经编写了所有可以看到的有趣内容;发布代码的唯一变化是复制超过 5000 行 ^^

很高兴你能给我任何帮助:)

谢谢,


编辑:这是来自 Qt Creator 的“编译输出”的代码:

g++ -c -pipe -fno-keep-inline-dllexport -g -frtti -Wall -Wextra -fexceptions -mthreads -DUNICODE -DMGENERALDEFINES_GUI -DMGENERALDEFINES_DEBUG -DMGENERALDEFINES_GENERAL -DQWT_INCLUDED -DDEBUG -DRELEASE -DQT_NO_DEBUG -DQT_NO_DEBUG_OUTPUT -DQT_PRINTSUPPORT_LIB -DQT_MULTIMEDIA_LIB -DQT_WIDGETS_LIB -DQT_SQL_LIB -DQT_NETWORK_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_NEEDS_QMAIN -I. -I"MSHARE_REPO" -I"MSHARE_COMMON" -I"C:\Qt\Qwt-6.1.0\include" -I"C:\Qt\Qt5.2.1\5.2.1\mingw48_32\include" -I"C:\Qt\Qt5.2.1\5.2.1\mingw48_32\include\QtPrintSupport" -I"C:\Qt\Qt5.2.1\5.2.1\mingw48_32\include\QtMultimedia" -I"C:\Qt\Qt5.2.1\5.2.1\mingw48_32\include\QtWidgets" -I"C:\Qt\Qt5.2.1\5.2.1\mingw48_32\include\QtSql" -I"C:\Qt\Qt5.2.1\5.2.1\mingw48_32\include\QtNetwork" -I"C:\Qt\Qt5.2.1\5.2.1\mingw48_32\include\QtGui" -I"C:\Qt\Qt5.2.1\5.2.1\mingw48_32\include\QtCore" -I"build\moc" -I"build\ui" -I"C:\Qt\Qt5.2.1\5.2.1\mingw48_32\mkspecs\win32-g++" -o build\obj\moc_mainwindow.o build\moc\moc_mainwindow.cpp
g++ -Wl,-subsystem,windows -mthreads -o debug\mShare.exe object_script.mShare.Debug  -lglu32 -lopengl32 -lgdi32 -luser32 -lmingw32 -lqtmaind "D:/Minhas obras/Softwares/mShare Project/mShare/SMTPEmail.dll" -lpsapi C:/Qt/Qwt-6.1.0/lib/qwtd.dll "D:/Minhas obras/Softwares/mShare Project/mShare/../../Classes/mLogger/build/debug/mLogger.dll" "D:/Minhas obras/Softwares/mShare Project/mShare/../mShareLib/build/debug/mShareLib.dll" C:/Qt/Qwt-6.1.0/lib/qwt.dll "D:/Minhas obras/Softwares/mShare Project/mShare/../../Classes/mLogger/build/release/mLogger.dll" "D:/Minhas obras/Softwares/mShare Project/mShare/../mShareLib/build/release/mShareLib.dll" -LC:\Qt\Qt5.2.1\5.2.1\mingw48_32\lib -lQt5PrintSupportd -lQt5Multimediad -lQt5Widgetsd -lQt5Sqld -lQt5Networkd -lQt5Guid -lQt5Cored .\build\obj\icone_res.o 
d000171.o:(.idata$5+0x0): multiple definition of `_imp___ZN13QwtPlotPicker16staticMetaObjectE'
d000022.o:(.idata$5+0x0): first defined here
d000171.o:(.idata$6+0x0): multiple definition of `_nm___ZN13QwtPlotPicker16staticMetaObjectE'
d000022.o:(.idata$6+0x0): first defined here
d000172.o:(.idata$5+0x0): multiple definition of `_imp___ZN9QwtThermo16staticMetaObjectE'
d000102.o:(.idata$5+0x0): first defined here
d000172.o:(.idata$6+0x0): multiple definition of `_nm___ZN9QwtThermo16staticMetaObjectE'
Makefile.Debug:246: recipe for target 'debug\mShare.exe' failed
d000102.o:(.idata$6+0x0): first defined here
collect2.exe: error: ld returned 1 exit status
mingw32-make[1]: [debug\mShare.exe] Error 1 (ignored)

【问题讨论】:

  • 您是否尝试过删除所有目标文件并从头开始重新编译?
  • @user657267 多次:T
  • 您可以复制文件而不是移动文件,这将解释多重定义错误。至于未定义的 vtable,您缺少成员函数的定义,或者可能没有将相关对象传递给链接器。
  • @n.m.感谢您的评论。好吧,这当然是我从未检查过的一种可能性,尽管我不会打赌(即使我已经复制而不是移动,我也不会在我的源代码中包含两次,我在这里没有我知道,所以我稍后会检查)。顺便说一句,如果这是问题所在,难道更多的课程不会出现同样的问题吗?请记住,我通常使用许多 Qwt 类,更不用说我自己的类了,只有那两个有问题。关于 vtable,我敢打赌这是普遍问题的结果;没有使用虚函数。

标签: c++ qt pointers


【解决方案1】:

我可能是错的,因为我不知道您的代码是什么样的,但听起来好像是多次编译这些类?如果您尚未将#pragma once 添加到头文件的顶部,以确保该类只有一个编译副本。希望您能尽快找到解决方案!

【讨论】:

  • 添加#pragma?这很奇怪,因为我从来不需要在我的一个代码中添加任何#pragma :P 你确定你不是在谈论上面 user2674995 谈到的#ifndef/#define 事情吗?如果不是,那#pragma 到底如何工作? (我的意思是把它放在哪里以及在它后面写什么)
  • #pragma once 位于头文件的顶部,以确保它只编译一次。 #ifndef MY_HEADER_H 是确保这一点的另一种方法,因为它会检查是否定义了定义,并将根据是否定义继续读取代码。正如 user3674995 指出的那样,#ifndef 将围绕感兴趣的代码。希望有帮助!
  • 感谢您的回复,但如上所述,它没有帮助;我的代码已经有 #ifndef 并且问题仍然存在。
  • 奇怪...您能否将您的一些代码添加到问题中,特别是有问题的标头/cpps?这将有助于尝试确定问题。
  • 感谢您的回复。如上所述,似乎与理解问题相关的所有内容都已编写;代码和往常一样正常:T 正如您在下面可能注意到的那样,我确实设法找到了问题所在 - 而且实际上它与源代码文件的安排无关:T 如果您能提供帮助,我会很高兴顺便说一句,我同意:只需搜索“qmake 没有正确读取我的 .pro”;谢谢!
【解决方案2】:

这里有几件事可能很有趣。我注意到您的错误涉及静态关键字。您的代码可能会声明静态变量并在许多地方对其进行初始化。

另一个原因可能是您没有使用ifndefpragma once 来确保只为所有类+ 标头初始化一个实例。 您需要在标题中添加这样的内容:

#ifndef MY_HEADER_H
#define MY_HEADER_H

... // all of your code

#endif

【讨论】:

  • @user2674995 感谢您的回答。我从来没有在我的源代码中使用过(从来没有使用过)#pragma,而且我认为解决这个问题的正确方法不是采用这样的“绕过”解决方案(至少它对我来说是这样的)。关于#ifndef,Qt Creator 会自动将它们添加到创建的任何类文件中,因此它们在我的代码中。关于静态,好吧,我现在不在这里使用代码,但据我所知,我没有在感兴趣的类中使用任何静态的东西。
【解决方案3】:

好吧,经过一些尝试和重试,我设法找到了问题所在 - 但不知道如何解决它。问题的存在是因为在我的 Qt .pro 文件中,我尝试为调试编译配置一些特定配置,为发布编译配置其他配置,但由于某种原因,系统没有区分这两种配置。更具体地说,以下代码应该可以工作:

win32 {
    LIBS += -lpsapi

    debug {
        LIBS += C:/Qt/Qwt-6.1.0/lib/qwtd.dll \
            $${MLOGGER}/build/debug/mLogger.dll \      
            $${MSHARE_LIB}/build/debug/mShareLib.dll  
        DEFINES += DEBUG
    }

    release {
        LIBS += C:/Qt/Qwt-6.1.0/lib/qwt.dll \
            $${MLOGGER}/build/release/mLogger.dll \
            $${MSHARE_LIB}/build/release/mShareLib.dll
        DEFINES += RELEASE \
           QT_NO_DEBUG \
           QT_NO_DEBUG_OUTPUT
    }
} # win32

因为在关于 qmake 的 Qt 助手文件中,这就是使用次要范围编写此类配置的方式:

win32 {
    debug {
        CONFIG += console
    }
}

我注意到,在注释了“发布”部分后,问题消失了,我能够毫无错误地编译;如果评论被删除,问题又回来了。同时,虽然没有注释,但我注意到发布定义已定义,尽管我处于调试编译“状态”。最后,这是我更改之前不存在的代码。

唯一的问题是:为什么 qmake 不能正确解释 .pro 文件?但我将把它放在另一个问题中。

感谢您的帮助,

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-19
    • 1970-01-01
    • 1970-01-01
    • 2013-12-16
    • 2018-03-05
    相关资源
    最近更新 更多