2015-10-26 3 views
0

Я создаю простую базу данных имени потока отладки (поскольку вы не можете указывать имя потока в окнах, вы можете отправлять это имя только в отладчик). У меня есть этот файл заголовка:Неразрешенный внешний символ для класса, который даже не повторяется

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)" ([email protected]@@[email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@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)" ([email protected]@@[email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@XZ) referenced in function "private: void __cdecl BaseRunPresenter::MessageHandler(class boost::shared_ptr)" ([email protected]@@[email protected]@@@[email protected]@@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)" ([email protected]@@[email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@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)" ([email protected]@@[email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@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)" ([email protected]@@[email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@XZ) D:\techsys\RomeoTT\Source\RunSestavaFrame.obj 
Error 18 error LNK2019: unresolved external symbol "class std::basic_string,class std::allocator > __cdecl getThreadName(void)" ([email protected]@[email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@XZ) referenced in function "public: void __cdecl SestavaHeader::DataSource::Dump2LOG(void)const " ([email protected]@[email protected]@QEBAXXZ) D:\techsys\RomeoTT\Source\SestavaDataSource.obj 

Я искал проект, но не единого упоминания о какой-либо из не статических методов класса, только один в logger.h.

Я проверил многие из вопросов внешних неиспользуемых символов, но все они пришли с двумя возможностями:

  1. дллов отсутствуют - ну, я не использую любой DLL для этого явно
  2. функции была объявлена но не реализован - в коде выше вы можете увидеть как декларации и реализации и они соответствие

Так почему линкер будет жаловаться на метод, который даже не ссылаются? Я попытался изменить const и переместить статический метод в файл .h, ничего не помогло. Сейчас я действительно отчаялся.

Edit: флаги 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 
+0

И вы строите с помощью 'threadname.cpp' и ссылаетесь на файл объекта, сгенерированный исходным файлом? –

+0

Какие фреймы компилятора и компоновщика вы используете? –

+0

На самом деле, все работало до того, как я выставил класс в заголовочном файле. Я начал с раскрытия функции и в 'cpp', вызывая класс из этой функции. Я добавлю флаги компилятора и компоновщика, но я сомневаюсь, что это актуально, я просто использую флаги visual studio visual. –

ответ

2

Вы найдете вероятный преступник, изучив подробно сообщения об ошибках (Начищенное для lisibility):

 
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, B aseRunPresenter.obj ...) Содержит ссылку на неконстантного метода getThreadName()
  • Это означает, что эти объектные файлы были получены из исходных файлов в то время, когда метод getThreadName() был объявлен неконстантной

Однако, декларация getThreadName() теперь Const:

std::string getThreadName() const; 

Таким образом, каждый из этих объектных файлов были Compi на основе устаревшего объявления getThreadName() и его необходимо перекомпилировать. Если возможно, так как могут быть другие (необнаруженные) ошибки несоответствия, вы должны выполнить полную перестройку.

+0

Чистая сборка исправила проблему, спасибо большое! –

 Смежные вопросы

  • Нет связанных вопросов^_^