Xin lỗi vì tháng này tôi chưa viết được gì thú vị, đây là một tháng rất bận rộn.
Hôm nay tôi thấy một câu hỏi trên Stack Overflow về debugging. Người dùng đang cố gắng chạy Visual Studio ở chế độ debug với ứng dụng của họ để xem khi nào và tại sao nó bị crash.
Đó không phải là giải pháp vì có các hàm trong Windows API dành cho những tình huống này. Nói đơn giản hơn, bạn có thể thiết lập phần mềm để viết một Mini Dump khi bị crash và sau đó bạn chỉ cần mở nó trong Visual Studio (hoặc bất kỳ trình gỡ lỗi nào bạn thích) và xem chính xác nơi nó bị crash.
Ví dụ sau đây có thể sử dụng ngay cho bất kỳ .exe hoặc .dll nào trên Windows:
1#pragma once
2
3#include <Windows.h>
4#include <Dbghelp.h>
5#pragma comment (lib, "Dbghelp.lib")
6
7// Because... why not ?!
8namespace MecanikUtils
9{
10LPTOP_LEVEL_EXCEPTION_FILTER PreviousExceptionFilter = 0;
11
12 LONG WINAPI DumpExceptionFilter(EXCEPTION_POINTERS* info)
13 {
14 wchar_t DumpPath[MAX_PATH] = { 0 };
15
16 SYSTEMTIME SystemTime;
17 GetLocalTime(&SystemTime);
18
19 WCHAR szExeFileName[100] = { 0 };
20 GetModuleFileNameW(NULL, szExeFileName, 99);
21
22 wsprintfW(DumpPath, L"Crash_%s_%d-%d-%d_%dh%dm%ds.dmp", szExeFileName, SystemTime.wYear, SystemTime.wMonth, SystemTime.wDay, SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond);
23
24 HANDLE file = CreateFileW(DumpPath, GENERIC_WRITE, FILE_SHARE_WRITE, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
25
26 if (file != INVALID_HANDLE_VALUE)
27 {
28 MINIDUMP_EXCEPTION_INFORMATION mdei;
29
30 mdei.ThreadId = (DWORD)GetCurrentThreadId();
31
32 mdei.ExceptionPointers = info;
33
34 mdei.ClientPointers = 0;
35
36 if (MiniDumpWriteDump(GetCurrentProcess(), (DWORD)GetCurrentProcessId(), file, (MINIDUMP_TYPE)(MiniDumpScanMemory + MiniDumpWithIndirectlyReferencedMemory), &mdei, 0, 0) != 0)
37 {
38 CloseHandle(file);
39 return EXCEPTION_EXECUTE_HANDLER;
40 }
41 }
42
43 CloseHandle(file);
44
45 return EXCEPTION_CONTINUE_SEARCH;
46 }
47
48 class MiniDump
49 {
50 public:
51
52 /// <summary>
53 /// Add Unhandled Exception Filter
54 /// </summary>
55 inline static void Init()
56 {
57 // Change if required
58 SetErrorMode(SEM_FAILCRITICALERRORS);
59
60 PreviousExceptionFilter = SetUnhandledExceptionFilter(DumpExceptionFilter);
61 }
62
63 /// <summary>
64 /// Remove Unhandled Exception Filter
65 /// </summary>
66 inline static void Clean()
67 {
68 SetUnhandledExceptionFilter(PreviousExceptionFilter);
69 }
70 };
71
72}Để sử dụng, chỉ cần gọi các hàm sau ở đầu và cuối điểm khởi đầu của phần mềm. Ví dụ một .dll:
1#include "MiniDump.hpp"
2
3BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved )
4{
5switch ( ul_reason_for_call )
6{
7case DLL_PROCESS_ATTACHED:
8MecanikUtils::MiniDump::Init();
9break;
10
11 case DLL_PROCESS_DETACH:
12 MecanikUtils::MiniDump::Clean();
13 break;
14
15}
16return TRUE;
17}Hãy thoải mái thực hiện các thay đổi đối với SetErrorMode nếu cần.
Lưu ý: Giữ lại tệp .pdb gốc của .exe/.dll đã biên dịch nếu bạn muốn mở Mini Dump. Nếu không, bạn sẽ không có thông tin dễ đọc.
Hẹn gặp lại! 😉
Bình luận