1

经过几个小时的挖掘这个链接器错误,它没有成功:(

重现步骤:

  1. 安装 gyp它到PATH
  2. 打开VS2015 x86 Native Tools Command Prompt
  3. 跑:
    • 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
  4. 打开src\client\windows\breakpad_client.sln
  5. 转到项目Properties>C/C++/General并更改Treat Warnings As ErrorsNocrash_generation_client、common、exception_handlerDebugRelease配置
  6. 转到项目Properties>C/C++/General并更改Treat wchar_t as Built-in TypeNocrash_generation_client、common、exception_handlerDebugRelease配置
  7. 一切为了Debug
  8. 一切为了Release
  9. 将位于您的应用程序中的库链接breakpad\src\client\windows\Debug\libbreakpad\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
}
  1. 链接器应通过以下错误提示您:

    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)

4

0 回答 0