测试有效,可以抓到 dump。
// 示例:基于 Crashpad 的 Windows 崩溃模拟与 dump 捕获
// 说明:
// - 默认使用 Windows DbgHelp 的 MiniDumpWriteDump 作为兜底;
// - 当定义 USE_CRASHPAD 且提供 crashpad_handler 与库时,启用 Crashpad 上报/采集;
// - 生成的 dump 输出到可执行文件旁的 artifacts/dumps 目录。
// 使用:
// - 正常构建运行:CrashPadSample.exe(默认立即触发崩溃)
// - 若需要参数控制,可改回解析 --crash 开关。
// 环境变量(启用 Crashpad 时可选):
// - CRASHPAD_HANDLER:crashpad_handler.exe 路径;为空则默认 bin/crashpad_handler.exe
// - CRASHPAD_INCLUDE:Crashpad 头文件目录(用于 CMake)
// - CRASHPAD_LIB_DIR:Crashpad 链接库目录(用于 CMake)
#include <windows.h>
#include <dbghelp.h>
#include <string>
#include <vector>
#include <filesystem>
#include <iostream>
#include <chrono>
#include <iomanip>
#include <sstream>
using namespace std;
#ifdef USE_CRASHPAD
#include "client/crashpad_client.h"
#include "client/crash_report_database.h"
#include "client/settings.h"
#include "base/files/file_path.h"
#endif
// 工具函数:UTF-8 转宽字符串(当前示例未用,可留作扩展)
static std::wstring WStringFromUtf8(const std::string& s) {
int len = MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, nullptr, 0);
std::wstring ws;
ws.resize(len ? len - 1 : 0);
if (len) MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, ws.data(), len);
return ws;
}
// 获取当前可执行文件所在目录
static std::wstring ModuleDir() {
wchar_t buffer[MAX_PATH];
GetModuleFileNameW(nullptr, buffer, MAX_PATH);
std::filesystem::path p(buffer);
return p.parent_path().wstring();
}
// 生成时间戳(YYYYMMDD_HHMMSS),用于 dump 文件名
static std::wstring Timestamp() {
auto now = std::chrono::system_clock::now();
auto t = std::chrono::system_clock::to_time_t(now);
std::tm tm{};
localtime_s(&tm, &t);
std::wstringstream ss;
ss << std::put_time(&tm, L"%Y%m%d_%H%M%S");
return ss.str();
}
// 未处理异常回调:写出本地 minidump(DbgHelp)
// 说明:
// - MiniDumpWithFullMemory | MiniDumpWithHandleData | MiniDumpWithThreadInfo
// 提供较完整的内存与线程上下文,便于分析;
// - 写入路径:<exe-dir>/artifacts/dumps/dssapp_<ts>.dmp
static LONG WINAPI DumpFilter(EXCEPTION_POINTERS* ep) {
std::filesystem::path base = ModuleDir();
std::filesystem::path dumps = base / L"artifacts" / L"dumps";
std::error_code ec;
std::filesystem::create_directories(dumps, ec);
std::filesystem::path file = dumps / (L"dssapp_" + Timestamp() + L".dmp");
HANDLE hFile = CreateFileW(file.c_str(), GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
if (hFile == INVALID_HANDLE_VALUE) return EXCEPTION_EXECUTE_HANDLER;
MINIDUMP_EXCEPTION_INFORMATION mei{};
mei.ThreadId = GetCurrentThreadId();
mei.ExceptionPointers = ep;
mei.ClientPointers = FALSE;
MINIDUMP_TYPE type = (MINIDUMP_TYPE)(MiniDumpWithFullMemory | MiniDumpWithHandleData | MiniDumpWithThreadInfo);
MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, type, &mei, nullptr, nullptr);
CloseHandle(hFile);
return EXCEPTION_EXECUTE_HANDLER;
}
// 人为制造访问违规以触发崩溃
static void CauseCrash() {
volatile int* p = nullptr;
*p = 1;
}
#ifdef USE_CRASHPAD
// 启动 Crashpad handler:
// - 优先从环境变量 CRASHPAD_HANDLER 读取 handler 路径;否则尝试 bin/crashpad_handler.exe
// - 数据库目录设为 artifacts/dumps(方便统一查看)
// - 打印路径与启动结果,便于定位集成问题
static bool StartCrashpad() {
std::wstring base = ModuleDir();
std::wstring dumps = (std::filesystem::path(base) / L"artifacts" / L"dumps").wstring();
std::wstring handler;
wchar_t* env = nullptr;
size_t sz = 0;
_wdupenv_s(&env, &sz, L"CRASHPAD_HANDLER");
if (env && sz) handler = env;
if (env) free(env);
if (handler.empty())
handler = (std::filesystem::path(base) / L"bin" / L"crashpad_handler.exe").wstring();
std::wcout << L"[Crashpad] Handler path: " << handler << std::endl;
std::wcout << L"[Crashpad] DB path: " << dumps << std::endl;
if (!std::filesystem::exists(handler)) {
std::wcout << L"[Crashpad] ERROR: handler does NOT exist!" << std::endl;
}
std::filesystem::create_directories(dumps);
if (!std::filesystem::exists(dumps)) {
std::wcout << L"[Crashpad] ERROR: dumps directory NOT created!" << std::endl;
}
crashpad::CrashpadClient client;
base::FilePath handler_path(handler);
base::FilePath db_path(dumps);
std::map<std::string, std::string> annotations;
std::vector<std::string> arguments;
bool success = client.StartHandler(handler_path, db_path, db_path, "",
annotations, arguments,
true /*restartable*/,
false /*async*/);
std::wcout << L"[Crashpad] StartHandler returned: " << success << std::endl;
return success;
}
#endif
int main(int argc, wchar_t* argv[]) {
// 程序入口:设置未处理异常过滤器、可选启动 Crashpad、触发崩溃
cout << "hello world";
SetUnhandledExceptionFilter(DumpFilter);
bool use_crash = true;
#ifdef USE_CRASHPAD
StartCrashpad();
#endif
if (use_crash) {
CauseCrash();
}
else {
OutputDebugStringW(L"CrashPadSample running. Use --crash to simulate crash.\n");
}
return 0;
}
17万+

被折叠的 条评论
为什么被折叠?



