经过几个小时的挖掘这个链接器错误,它没有成功:(
重现步骤:
- 安装
gyp
它到PATH
- 打开
VS2015 x86 Native Tools Command Prompt
- 跑:
git clone https://chromium.googlesource.com/breakpad/breakpad && cd breakpad
cd src && git clone https://github.com/google/googletest testing && cd ..
gyp -–no-circular-check src\client\windows\breakpad_client.gyp
- 打开
src\client\windows\breakpad_client.sln
- 转到项目
Properties>C/C++/General
并更改Treat Warnings As Errors
为No
crash_generation_client、common、exception_handlerDebug
和Release
配置 - 转到项目
Properties>C/C++/General
并更改Treat wchar_t as Built-in Type
为No
crash_generation_client、common、exception_handlerDebug
和Release
配置 - 一切为了
Debug
- 一切为了
Release
- 将位于您的应用程序中的库链接
breakpad\src\client\windows\Debug\lib
到breakpad\src\client\windows\Release\lib
您的应用程序,在我的情况下,Qt qmake
文件如下所示:
win32:debug {
BREAKPAD_PATH = $$PWD/../../../LIBS/breakpad
INCLUDEPATH += $$BREAKPAD_PATH/src
LIBS += -L$$BREAKPAD_PATH/client/windows/Debug/lib/crash_generation_client.lib
LIBS += -L$$BREAKPAD_PATH/client/windows/Debug/lib/exception_handler.lib
LIBS += -L$$BREAKPAD_PATH/client/windows/Debug/lib/common.lib
PRE_TARGETDEPS += $$BREAKPAD_PATH/client/windows/Debug/lib/crash_generation_client.lib
PRE_TARGETDEPS += $$BREAKPAD_PATH/client/windows/Debug/lib/exception_handler.lib
PRE_TARGETDEPS += $$BREAKPAD_PATH/client/windows/Debug/lib/common.lib
} else:release {
BREAKPAD_PATH = $$PWD/../../../LIBS/breakpad
INCLUDEPATH += $$BREAKPAD_PATH/src
LIBS += -L$$BREAKPAD_PATH/client/windows/Release/lib/crash_generation_client.lib
LIBS += -L$$BREAKPAD_PATH/client/windows/Release/lib/exception_handler.lib
LIBS += -L$$BREAKPAD_PATH/client/windows/Release/lib/common.lib
PRE_TARGETDEPS += $$BREAKPAD_PATH/client/windows/Release/lib/crash_generation_client.lib
PRE_TARGETDEPS += $$BREAKPAD_PATH/client/windows/Release/lib/exception_handler.lib
PRE_TARGETDEPS += $$BREAKPAD_PATH/client/windows/Release/lib/common.lib
}
- 链接器应通过以下错误提示您:
crash_handler.obj:错误 LNK2019:无法解析的外部符号“公共:__thiscall google_breakpad::ExceptionHandler::ExceptionHandler(class std::basic_string,class std::allocator > const &,bool (__cdecl*)(void *,struct _EXCEPTION_POINTERS *,结构 MDRawAssertionInfo ),bool (__cdecl)(wchar_t const *,wchar_t const *,void *,struct _EXCEPTION_POINTERS *,struct MDRawAssertionInfo *,bool),void *,int)" (??0ExceptionHandler@google_breakpad@@QAE@ABV?$basic_string@_WU?$char_traits@ _W@std@@V?$allocator@_W@2@@std@@P6A_NPAXPAU_EXCEPTION_POINTERS@@PAUMDRawAssertionInfo@@@ZP6A_NPB_W5123_N@Z1H@Z) 在函数“public: void __thiscall breakpad::CrashHandlerPrivate::initCrashHandler(class QString const &)" (?initCrashHandler@CrashHandlerPrivate@breakpad@@QAEXABVQString@@@Z) crash_handler.obj : 错误 LNK2019: 无法解析的外部符号 "public: __thiscall google_breakpad::ExceptionHandler::~ExceptionHandler(void)" (??1ExceptionHandler@google_breakpad @@QAE@XZ) 在函数“public: void * __thiscall google_breakpad::ExceptionHandler::`标量删除析构函数”中引用(unsigned int)" (??_GExceptionHandler@google_breakpad@@QAEPAXI@Z) crash_handler.obj : 错误 LNK2019: 无法解析的外部符号 "public: bool __thiscall google_breakpad::ExceptionHandler::WriteMinidump(void)" (?WriteMinidump@ExceptionHandler@google_breakpad @@QAE_NXZ) 在函数 "public: bool __thiscall breakpad::CrashHandler::writeMinidump(void)" (?writeMinidump@CrashHandler@breakpad@@QAE_NXZ) 中引用(?writeMinidump@CrashHandler@breakpad@@QAE_NXZ)(?writeMinidump@CrashHandler@breakpad@@QAE_NXZ)
crash_handler.h
:
#ifndef _CRASH_HANDLER_H
#define _CRASH_HANDLER_H
namespace breakpad {
class CrashHandlerPrivate;
class CrashHandler {
public:
static CrashHandler* instance();
void init(const QString& reportPath);
void setReportCrashesToSystem(bool report);
bool writeMinidump();
private:
CrashHandler();
~CrashHandler();
private:
CrashHandlerPrivate* d;
Q_DISABLE_COPY(CrashHandler)
};
} // namespace breakpad
#endif // !_CRASH_HANDLER_H
crash_handler.cpp
#include "crash_handler.h"
#if defined(Q_OS_LINUX)
#include "client/linux/handler/exception_handler.h"
#elif defined(Q_OS_WIN32)
#include "client/windows/handler/exception_handler.h"
#endif
namespace breakpad {
class CrashHandlerPrivate {
public:
CrashHandlerPrivate() {
pHandler = NULL;
}
~CrashHandlerPrivate() {
delete pHandler;
}
void initCrashHandler(const QString& dumpPath);
public:
static google_breakpad::ExceptionHandler* pHandler;
static bool bReportCrashesToSystem;
};
google_breakpad::ExceptionHandler* CrashHandlerPrivate::pHandler = NULL;
bool CrashHandlerPrivate::bReportCrashesToSystem = false;
/************************************************************************/
/* DumpCallback */
/************************************************************************/
#if defined(Q_OS_WIN32)
bool DumpCallback(const wchar_t* _dump_dir, const wchar_t* _minidump_id, void* context, EXCEPTION_POINTERS* exinfo, MDRawAssertionInfo* assertion, bool success)
#elif defined(Q_OS_LINUX)
bool DumpCallback(const google_breakpad::MinidumpDescriptor &md, void *context, bool success)
#endif
{
Q_UNUSED(context);
#if defined(Q_OS_WIN32)
Q_UNUSED(_dump_dir);
Q_UNUSED(_minidump_id);
Q_UNUSED(assertion);
Q_UNUSED(exinfo);
#endif
qDebug("BreakpadQt crash");
/*
NO STACK USE, NO HEAP USE THERE !!!
Creating QString's, using qDebug, etc. - everything is crash-unfriendly.
*/
return CrashHandlerPrivate::bReportCrashesToSystem ? success : true;
}
void CrashHandlerPrivate::initCrashHandler(const QString& dumpPath)
{
if (pHandler != NULL)
return;
#if defined(Q_OS_WIN32)
std::wstring pathAsStr = (const wchar_t*)dumpPath.utf16();
pHandler = new google_breakpad::ExceptionHandler(
pathAsStr,
/*FilterCallback*/ 0,
DumpCallback,
/*context*/
0,
true
);
#elif defined(Q_OS_LINUX)
std::string pathAsStr = dumpPath.toStdString();
google_breakpad::MinidumpDescriptor md(pathAsStr);
pHandler = new google_breakpad::ExceptionHandler(
md,
/*FilterCallback*/ 0,
DumpCallback,
/*context*/ 0,
true,
-1
);
#endif
}
CrashHandler* CrashHandler::instance() {
static CrashHandler globalHandler;
return &globalHandler;
}
CrashHandler::CrashHandler() {
d = new CrashHandlerPrivate();
}
CrashHandler::~CrashHandler() {
delete d;
}
void CrashHandler::setReportCrashesToSystem(bool report) {
d->bReportCrashesToSystem = report;
}
bool CrashHandler::writeMinidump() {
bool res = d->pHandler->WriteMinidump();
if (res) {
qDebug("BreakpadQt: writeMinidump() success.");
} else {
qWarning("BreakpadQt: writeMinidump() failed.");
}
return res;
}
void CrashHandler::init(const QString& reportPath) {
d->initCrashHandler(reportPath);
}
} // namespace breakpad
真的不知道是什么问题?!
配置:
操作系统:
Windows 10(1809)
构建系统:
MSVC14.0(2015)
Qt版本:
5.8(32bit)