甚至未被引用的类方法的未解析外部符号
Unresolved external symbol for classmethod that isn't even referenced
我正在创建一个简单的调试线程名称数据库(因为您不能在 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() {
static ThreadNameMap inst = ThreadNameMap();
return &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());
if(id==-1)
id = boostThreadId();
names[id] = name;
}
std::string ThreadNameMap::getThreadName( const uint32_t id ) const {
if( names.count( id )>0)
return names.at(id);
else
return "";
}
std::string ThreadNameMap::getThreadName( const std::string id ) const {
uint32_t threadNumber = 0;
sscanf(id.c_str(), "%lx", &threadNumber);
return getThreadName(threadNumber);
}
/** THIS ONE IS REPORTED AS UNREFERENCED!!! **/
std::string ThreadNameMap::getThreadName( ) const {
return getThreadName(boostThreadId());
}
我使用单例接口并在我的记录器头文件中像这样访问它:
logger.h
#include "... path .../setthreadname.h"
#define LOGMTDBG_tmp(debuglevel, logstream) LOGMT(debugLevel(debuglevel) << datetimeEx << ' ' << ThreadNameMap::getName() << ' ' << __FUNCTION__ << ' ' << logstream)
Logger 包含在许多其他 cpp
和 h
文件中 - 任何需要的地方。其中一些报告未引用的符号:
Error 13 error LNK2001: unresolved external symbol "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
Error 14 error LNK2019: unresolved external symbol "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) referenced in function "private: void __cdecl BaseRunPresenter::MessageHandler(class boost::shared_ptr)" (?MessageHandler@BaseRunPresenter@@AEAAXV?$shared_ptr@USMSSBase@@@boost@@@Z) D:\techsys\RomeoTT\Source\BaseRunPresenter.obj
Error 15 error LNK2001: unresolved external symbol "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
Error 16 error LNK2001: unresolved external symbol "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
Error 17 error LNK2001: unresolved external symbol "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
Error 18 error LNK2019: unresolved external symbol "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) referenced in function "public: void __cdecl SestavaHeader::DataSource::Dump2LOG(void)const " (?Dump2LOG@DataSource@SestavaHeader@@QEBAXXZ) D:\techsys\RomeoTT\Source\SestavaDataSource.obj
我搜索了项目,但没有任何class非静态方法的单一引用,只有[中的一个=14=].
我查了很多Unreferenced external symbol的问题,但是都是两种可能:
- 缺少 dll - 好吧,显然我没有为此使用任何 dll
- 函数已声明但未实现 - 在上面的代码中您可以看到声明和实现,它们匹配
那么为什么链接器会抱怨甚至没有引用的方法?我试图改变 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.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
您通过详细检查错误消息(清理易感性)找到可能的罪魁祸首:
Unresolved external symbol "string stringThreadNameMap::getThreadName(void)" referenced in RunWindow.obj
Unresolved external symbol "string stringThreadNameMap::getThreadName(void)" referenced in function "private: void stringBaseRunPresenter::MessageHandler(class boost::shared_ptr)" referenced in BaseRunPresenter.obj
Unresolved external symbol "string stringThreadNameMap::getThreadName(void)" referenced in BaseRunView.obj
Unresolved external symbol "string stringThreadNameMap::getThreadName(void)" referenced in XmlSestavaRunPresenter.obj
Unresolved external symbol "string stringThreadNameMap::getThreadName(void)" referenced in RunSestavaFrame.obj
Unresolved external symbol "string stringThreadNameMap::getThreadName(void)" referenced in function "public: void stringSestavaHeader::DataSource::Dump2LOG(void)const " SestavaDataSource.obj
这些链接器错误说明的是:
- 一些目标文件(RunWindow.obj、BaseRunPresenter.obj...)包含对 非常量 方法的引用
getThreadName()
- 这意味着这些目标文件是在声明方法
getThreadName()
时从源文件生成的 非常量
但是,getThreadName()
的声明现在是 const:
std::string getThreadName( ) const;
因此,这些目标文件中的每一个都是根据 getThreadName()
的过时声明编译的,应该重新编译。如果可能,因为可能存在其他(未检测到的)不一致错误,您应该执行完全重建。
我正在创建一个简单的调试线程名称数据库(因为您不能在 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() { static ThreadNameMap inst = ThreadNameMap(); return &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()); if(id==-1) id = boostThreadId(); names[id] = name; } std::string ThreadNameMap::getThreadName( const uint32_t id ) const { if( names.count( id )>0) return names.at(id); else return ""; } std::string ThreadNameMap::getThreadName( const std::string id ) const { uint32_t threadNumber = 0; sscanf(id.c_str(), "%lx", &threadNumber); return getThreadName(threadNumber); } /** THIS ONE IS REPORTED AS UNREFERENCED!!! **/ std::string ThreadNameMap::getThreadName( ) const { return getThreadName(boostThreadId()); }
我使用单例接口并在我的记录器头文件中像这样访问它:
logger.h
#include "... path .../setthreadname.h" #define LOGMTDBG_tmp(debuglevel, logstream) LOGMT(debugLevel(debuglevel) << datetimeEx << ' ' << ThreadNameMap::getName() << ' ' << __FUNCTION__ << ' ' << logstream)
Logger 包含在许多其他 cpp
和 h
文件中 - 任何需要的地方。其中一些报告未引用的符号:
Error 13 error LNK2001: unresolved external symbol "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 Error 14 error LNK2019: unresolved external symbol "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) referenced in function "private: void __cdecl BaseRunPresenter::MessageHandler(class boost::shared_ptr)" (?MessageHandler@BaseRunPresenter@@AEAAXV?$shared_ptr@USMSSBase@@@boost@@@Z) D:\techsys\RomeoTT\Source\BaseRunPresenter.obj Error 15 error LNK2001: unresolved external symbol "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 Error 16 error LNK2001: unresolved external symbol "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 Error 17 error LNK2001: unresolved external symbol "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 Error 18 error LNK2019: unresolved external symbol "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) referenced in function "public: void __cdecl SestavaHeader::DataSource::Dump2LOG(void)const " (?Dump2LOG@DataSource@SestavaHeader@@QEBAXXZ) D:\techsys\RomeoTT\Source\SestavaDataSource.obj
我搜索了项目,但没有任何class非静态方法的单一引用,只有[中的一个=14=].
我查了很多Unreferenced external symbol的问题,但是都是两种可能:
- 缺少 dll - 好吧,显然我没有为此使用任何 dll
- 函数已声明但未实现 - 在上面的代码中您可以看到声明和实现,它们匹配
那么为什么链接器会抱怨甚至没有引用的方法?我试图改变 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.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
您通过详细检查错误消息(清理易感性)找到可能的罪魁祸首:
Unresolved external symbol "string stringThreadNameMap::getThreadName(void)" referenced in RunWindow.obj Unresolved external symbol "string stringThreadNameMap::getThreadName(void)" referenced in function "private: void stringBaseRunPresenter::MessageHandler(class boost::shared_ptr)" referenced in BaseRunPresenter.obj Unresolved external symbol "string stringThreadNameMap::getThreadName(void)" referenced in BaseRunView.obj Unresolved external symbol "string stringThreadNameMap::getThreadName(void)" referenced in XmlSestavaRunPresenter.obj Unresolved external symbol "string stringThreadNameMap::getThreadName(void)" referenced in RunSestavaFrame.obj Unresolved external symbol "string stringThreadNameMap::getThreadName(void)" referenced in function "public: void stringSestavaHeader::DataSource::Dump2LOG(void)const " SestavaDataSource.obj
这些链接器错误说明的是:
- 一些目标文件(RunWindow.obj、BaseRunPresenter.obj...)包含对 非常量 方法的引用
getThreadName()
- 这意味着这些目标文件是在声明方法
getThreadName()
时从源文件生成的 非常量
但是,getThreadName()
的声明现在是 const:
std::string getThreadName( ) const;
因此,这些目标文件中的每一个都是根据 getThreadName()
的过时声明编译的,应该重新编译。如果可能,因为可能存在其他(未检测到的)不一致错误,您应该执行完全重建。