【问题标题】:Unresolved external symbol for classmethod that isn't even referenced甚至没有被引用的类方法的未解析外部符号
【发布时间】:2016-01-25 15:13:06
【问题描述】:

我正在创建一个简单的调试线程名称数据库(因为您不能在 Windows 中为线程命名,您只能将该名称发送给调试器)。我有这个头文件:

threadname.h

class ThreadNameMap {
public:
    void setThreadName( uint32_t id, const std::string &name );

    std::string getThreadName( const uint32_t id ) const;
    // If ID given as string
    std::string getThreadName( const std::string id ) const;
    // If no ID given, current ID is used
    std::string getThreadName( ) const;

    // A singleton getter
    static ThreadNameMap* ThreadNameMap::getInstance();
    // Static getters that use the singleton
    static std::string getName( const uint32_t id );
    static std::string getName( const std::string id );
    static std::string getName( );
private:
    ThreadNameMap() {maxNameLength = 16;};
    int maxNameLength;
    // Map of ids and names
    std::map<uint32_t, std::string> names;
}; 

这是实现:

threadname.cpp

ThreadNameMap* ThreadNameMap::getInstance() { 静态 ThreadNameMap inst = ThreadNameMap(); 返回 &inst; } std::string ThreadNameMap::getName( const uint32_t id ) { return getInstance()->getThreadName(id); } std::string ThreadNameMap::getName( const std::string id ) { return getInstance()->getThreadName(id); } std::string ThreadNameMap::getName() { return getInstance()->getThreadName(); } void ThreadNameMap::setThreadName(uint32_t id, const std::string &name) { setThreadName_private(id, name.c_str()); 如果(id==-1) id = boostThreadId(); 名称[id] = 名称; } std::string ThreadNameMap::getThreadName( const uint32_t id ) const { if(names.count(id)>0) 返回名称.at(id); 别的 返回 ””; } std::string ThreadNameMap::getThreadName( const std::string id ) const { uint32_t threadNumber = 0; sscanf(id.c_str(), "%lx", &threadNumber); 返回 getThreadName(threadNumber); } /** 这个被报告为未引用!!! **/ std::string ThreadNameMap::getThreadName() const { 返回 getThreadName(boostThreadId()); }

我使用单例接口,并在我的记录器头文件中这样访问它:

logger.h

#include "... 路径 .../setthreadname.h" #define LOGMTDBG_tmp(debuglevel, logstream) LOGMT(debugLevel(debuglevel) ThreadNameMap::getName()

Logger 包含在许多其他 cpph 文件中 - 只要需要。其中一些报告未引用的符号:

错误 13 错误 LNK2001: 无法解析的外部符号“public: class std::basic_string,class std::allocator > __cdecl ThreadNameMap::getThreadName(void)”(?getThreadName@ThreadNameMap@@QEAA?AV?$basic_string@DU?$char_traits @D@std@@V?$allocator@D@2@@std@@XZ) D:\techsys\RomeoTT\Source\RunWindow.obj 错误 14 错误 LNK2019:无法解析的外部符号“public: class std::basic_string,class std::allocator > __cdecl ThreadNameMap::getThreadName(void)”(?getThreadName@ThreadNameMap@@QEAA?AV?$basic_string@DU?$char_traits @D@std@@V?$allocator@D@2@@std@@XZ) 在函数 "private: void __cdecl BaseRunPresenter::MessageHandler(class boost::shared_ptr)" (?MessageHandler@BaseRunPresenter@@AEAAXV? $shared_ptr@USMSSBase@@@boost@@@Z) D:\techsys\RomeoTT\Source\BaseRunPresenter.obj 错误 15 错误 LNK2001:无法解析的外部符号“public:class std::basic_string,class std::allocator > __cdecl ThreadNameMap::getThreadName(void)”(?getThreadName@ThreadNameMap@@QEAA?AV?$basic_string@DU?$char_traits @D@std@@V?$allocator@D@2@@std@@XZ) D:\techsys\RomeoTT\Source\BaseRunView.obj 错误 16 错误 LNK2001:未解析的外部符号“public:class std::basic_string,class std::allocator > __cdecl ThreadNameMap::getThreadName(void)”(?getThreadName@ThreadNameMap@@QEAA?AV?$basic_string@DU?$char_traits @D@std@@V?$allocator@D@2@@std@@XZ) D:\techsys\RomeoTT\Source\XmlSestavaRunPresenter.obj 错误 17 错误 LNK2001:未解析的外部符号“public:class std::basic_string,class std::allocator > __cdecl ThreadNameMap::getThreadName(void)”(?getThreadName@ThreadNameMap@@QEAA?AV?$basic_string@DU?$char_traits @D@std@@V?$allocator@D@2@@std@@XZ) D:\techsys\RomeoTT\Source\RunSestavaFrame.obj 错误 18 错误 LNK2019: 无法解析的外部符号 "class std::basic_string,class std::allocator > __cdecl getThreadName(void)" (?getThreadName@@YA?AV?$basic_string@DU?$char_traits@D@std@@V ?$allocator@D@2@@std@@XZ) 在函数“public: void __cdecl SestavaHeader::DataSource::Dump2LOG(void)const” (?Dump2LOG@DataSource@SestavaHeader@@QEBAXXZ) D:\techsys\ 中引用RomeoTT\Source\SestavaDataSource.obj

搜索了项目,但没有任何类非静态方法的单一引用,只有 logger.h 中的一个。

我检查了许多未引用的外部符号问题,但它们都有两种可能性:

  1. dll 丢失 - 好吧,我显然没有为此使用任何 dll
  2. 函数已声明但未实现 - 在上面的代码中,您可以看到声明和实现,并且它们是匹配的

那么为什么链接器会抱怨甚至没有被引用的方法呢?我试图改变const 并在.h 文件中移动静态方法,没有任何帮助。我现在真的很绝望。

编辑: Visual Studio 链接器标志:

/OUT:"D:\techsys\RomeoTT\PROJECT\PROJECTd.exe" /INCREMENTAL /NOLOGO /LIBPATH:"..\..\libs\openssl64\lib\VC\static" /LIBPATH:"..\..\libs\boost155\stage\lib64bit" /LIBPATH:"C:\Qt\5.3.0-64\qtbase\lib" "libeay32MTd.lib" "Graph64d.lib" "HelpLib64d.lib" "version.lib" "qtmaind.lib" "Qt5Cored.lib" "Qt5Guid.lib" "Qt5Multimediad.lib" "Qt5Sqld.lib" "Qt5PrintSupportd.lib" "Qt5Svgd.lib" "Qt5Widgetsd.lib" "Qt5Xmld.lib" "Qt5XmlPatternsd.lib" "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" /MANIFEST /ManifestFile:"D:\techsys\XXXX\obj\x64\XXXX\Debug\XXXXXd.exe.intermediate.manifest" /ALLOWISOLATION /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"D:\techsys\XXXXX\XXXXX64\XXXXXd.pdb" /SUBSYSTEM:WINDOWS /OPT:NOREF /PGD:"D:\techsys\XXXX\XXXX64\XXXXXd.pgd" /TLBID:1 /DYNAMICBASE /NXCOMPAT /MACHINE:X64 /ERRORREPORT:NONE 

【问题讨论】:

  • 你用threadname.cpp构建并链接到源文件生成的目标文件?
  • 查看链接器抱怨的源代码。这似乎是直接调用 getThreadName() (您的记录器正在调用 getName)。还有一个文件是在没有类名的情况下调用 getThreadName(错误的最后一行)
  • 看起来RunWindow.obj 等文件指的是该符号。分享有问题的来源怎么样?顺便说一下,一个最小的、完整的、可验证的例子(stackoverflow.com/help/mcve)怎么样?准备 MCVE 本身实际上可以揭示问题。
  • 我仍然认为它与实现是一个 const 成员函数有关,而标题广告一个非常量成员函数。没有非常量 getName() 的实现。
  • @TomášZato 这更有理由创建一个最小、完整、可验证的示例。如果您非常确定参考来自发布的来源,那么您应该能够查明您的问题,但您显然没有自从您提出要求。如果所有引用都在发布的代码中,您应该能够将其包装起来并使其完整(并查看该示例中的问题是否可验证)。

标签: c++ c++11 linker-errors unresolved-external


【解决方案1】:

您可以通过详细检查错误消息来找到可能的罪魁祸首(清理了易读性):

RunWindow.obj 中引用的未解析外部符号“string stringThreadNameMap::getThreadName(void)” BaseRunPresenter.obj 中引用的函数“private: void stringBaseRunPresenter::MessageHandler(class boost::shared_ptr)”中引用的未解析外部符号“string stringThreadNameMap::getThreadName(void)” BaseRunView.obj 中引用的未解析外部符号“string stringThreadNameMap::getThreadName(void)” XmlSestavaRunPresenter.obj 中引用的未解析外部符号“string stringThreadNameMap::getThreadName(void)” RunSestavaFrame.obj 中引用的未解析外部符号“string stringThreadNameMap::getThreadName(void)” 函数“public: void stringSestavaHeader::DataSource::Dump2LOG(void)const” SestavaDataSource.obj 中引用的未解析外部符号“string stringThreadNameMap::getThreadName(void)”

这些链接器错误说明的是:

  • 某些对象文件(RunWindow.obj、BaseRunPresenter.obj...)包含对 非 const 方法 getThreadName() 的引用
  • 这意味着这些目标文件是在声明方法getThreadName() 非const时从源文件生成的

但是,getThreadName() 的声明现在是 const

std::string getThreadName( ) const;

因此,这些目标文件中的每一个都是根据过时的 getThreadName() 声明编译的,应该重新编译。如果可能,由于可能存在其他(未检测到的)不一致错误,您应该执行完全重建。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-05-25
    • 2010-09-30
    • 1970-01-01
    • 1970-01-01
    • 2013-09-13
    • 1970-01-01
    • 2011-02-09
    相关资源
    最近更新 更多