рдХреНрдпреЛрдВ рдФрд░ рдХрд┐рд╕рд▓рд┐рдП
рд╡рд┐рдХрд╛рд╕ рдХреЗ рджреМрд░рд╛рди, рдЪреАрдЬреЗрдВ рд╣рдореЗрд╢рд╛ рдЪрд┐рдХрдиреА рдирд╣реАрдВ рд╣реЛрддреА рд╣реИрдВред рдРрд╕реА рд╕рдорд╕реНрдпрд╛рдПрдВ рд╣реИрдВ рдЬреЛ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдкрд░ рдкреЙрдк рдЕрдк рдирд╣реАрдВ рдХрд░рддреА рд╣реИрдВ, рд▓реЗрдХрд┐рди рд░рд┐рд▓реАрдЬ рдХреЗ рдмрд╛рджред рдРрд╕реЗ рдорд╛рдорд▓реЛрдВ рдХреЗ рд▓рд┐рдП, рд╣рдордиреЗ рдЕрдкрд╡рд╛рджреЛрдВ рдФрд░ рдЖрдВрддрд░рд┐рдХ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдкрдХрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЫреЛрдЯреА рдкреНрд░рдгрд╛рд▓реА рдмрдирд╛рдИред
рдЕрдкрд╡рд╛рдж рдХреИрдЪ
рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХреЗ рд▓рд┐рдП рд╣рдореЗрдВ рдХреНрд░реИрд╢ (рдбрд┐рдмрдЧрд░ рдХреЗ рдмрд╛рд╣рд░) рд╕реЗ рдкрд╣рд▓реЗ рдпрд╣ рдмрддрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рд╕рдорд╕реНрдпрд╛ рдХреНрдпрд╛ рд╣реИ, рдЖрдк рд╕рд┐рдЧреНрдирд▓ рдкреНрд░реЛрд╕реЗрд╕рд┐рдВрдЧ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ ред
рдРрд╕реЗ рд╕рдВрдХреЗрддреЛрдВ рдХреЗ рдХреБрдЫ рдЙрджрд╛рд╣рд░рдг:
signal(SIGABRT, abort_handler);
signal(SIGFPE, floating_point_handler);
signal(SIGILL, illegal_instruction_handler);
рд╕рд┐рдЧреНрдирд▓ рд╕рдВрдЪрд╛рд▓рдХреЛрдВ
inline void abort_handler(int signal)
{
handler_base("Application is aborting");
}
inline void floating_point_handler(int signal)
{
handler_base("Floating point error");
}
inline void illegal_instruction_handler(int signal)
{
if (!CPU::Info.hasFeature(CPUFeature::SSE42))
handler_base("SSE4.2 and AVX instructions isn't legal on your CPU");
else if (!CPU::Info.hasFeature(CPUFeature::AVX))
handler_base("AVX instructions isn't legal on your CPU");
else
handler_base("Illegal instruction");
}
(_set_invalid_parameter_handler), (_set_new_handler) .
: callstack'a
, , . , CallStack. : StackWalker
: dump-
, Dump .
using MINIDUMPWRITEDUMP = BOOL(WINAPI*)(HANDLE hProcess, DWORD dwPid, HANDLE hFile, MINIDUMP_TYPE DumpType,
CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam
);
LONG WriteMinidump(struct _EXCEPTION_POINTERS* pExceptionInfo)
{
long retval = EXCEPTION_CONTINUE_SEARCH;
HMODULE hDll = nullptr;
string_path szDbgHelpPath;
if (GetModuleFileName(nullptr, szDbgHelpPath, _MAX_PATH))
{
char* pSlash = strchr(szDbgHelpPath, '\\');
if (pSlash)
{
const char dbgHelpStr[] = "DBGHELP.DLL";
xr_strcpy(pSlash + 1, sizeof(dbgHelpStr), dbgHelpStr);
hDll = LoadLibraryA(szDbgHelpPath);
}
}
if (!hDll)
{
hDll = LoadLibraryA("DBGHELP.DLL");
}
LPCSTR szResult = nullptr;
if (hDll)
{
MINIDUMPWRITEDUMP pDump = (MINIDUMPWRITEDUMP)::GetProcAddress(hDll, "MiniDumpWriteDump");
if (pDump)
{
string512 ErrorString = { NULL };
DWORD ErrorSysCode = NULL;
DWORD ErrorStringSize = NULL;
string_path szDumpPath = { 0 };
string_path szFilename = { 0 };
string_path szScratch = { 0 };
string64 t_stemp = { 0 };
timestamp(t_stemp);
xr_strcat(szDumpPath, DumpFilePath);
xr_strcat(szFilename, Core.ApplicationName);
xr_strcat(szFilename, "_");
xr_strcat(szFilename, Core.UserName);
xr_strcat(szFilename, "_");
xr_strcat(szFilename, t_stemp);
xr_strcat(szFilename, ".mdmp");
xr_strcat(szDumpPath, szFilename);
HANDLE hFile = CreateFileA(szDumpPath, GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
if (INVALID_HANDLE_VALUE == hFile)
{
ZeroMemory(szDumpPath, sizeof(szDumpPath));
xr_strcat(szDumpPath, szFilename);
hFile = CreateFileA(szDumpPath, GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
}
if (hFile != INVALID_HANDLE_VALUE)
{
_MINIDUMP_EXCEPTION_INFORMATION ExInfo;
ExInfo.ThreadId = GetCurrentThreadId();
ExInfo.ExceptionPointers = pExceptionInfo;
ExInfo.ClientPointers = NULL;
MINIDUMP_TYPE dump_flags = MINIDUMP_TYPE(MiniDumpNormal | MiniDumpFilterMemory | MiniDumpScanMemory);
char* logFileContent = nullptr;
DWORD logFileContentSize = 0;
MINIDUMP_USER_STREAM_INFORMATION UserStreamsInfo = { 0 };
MINIDUMP_USER_STREAM LogFileUserStream = { 0 };
if (logFileContent)
{
UserStreamsInfo.UserStreamCount = 1;
LogFileUserStream.Buffer = logFileContent;
LogFileUserStream.BufferSize = logFileContentSize;
LogFileUserStream.Type = MINIDUMP_STREAM_TYPE::CommentStreamA;
UserStreamsInfo.UserStreamArray = &LogFileUserStream;
}
BOOL bOK = pDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, dump_flags, &ExInfo, &UserStreamsInfo, nullptr);
if (bOK)
{
xr_sprintf(szScratch, "Saved dump file to '%s'", szDumpPath);
szResult = szScratch;
retval = EXCEPTION_EXECUTE_HANDLER;
}
else
{
ErrorSysCode = GetLastError();
ErrorStringSize = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, ErrorSysCode, 0, ErrorString, sizeof(ErrorString) - 1, nullptr);
if (!!ErrorString && ErrorSysCode && ErrorStringSize)
xr_sprintf(szScratch, "Failed to save dump file to '%s' (error %d '%s')", szDumpPath, ErrorSysCode, ErrorString);
else
xr_sprintf(szScratch, "Failed to save dump file to '%s' (No system error)", szDumpPath);
szResult = szScratch;
}
CloseHandle(hFile);
}
else
{
ErrorSysCode = GetLastError();
ErrorStringSize = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, ErrorSysCode, 0, ErrorString, sizeof(ErrorString) - 1, nullptr);
if (!!ErrorString && ErrorSysCode && ErrorStringSize)
xr_sprintf(szScratch, "Failed to create dump file '%s' (error %d '%s')", szDumpPath, ErrorSysCode, ErrorString);
else
xr_sprintf(szScratch, "Failed to create dump file '%s' (No system error)", szDumpPath);
szResult = szScratch;
}
}
else
szResult = "DBGHELP.DLL too old";
}
else
szResult = "DBGHELP.DLL not found";
return retval;
}
, , (, , ), , :

C# + WPF,
:
- рдХрд╛рд░реНрдпрдХреНрд░рдо рдХрд╛ рдирд┐рд╖реНрдкрд╛рджрди рдЬрд╛рд░реА рд░рдЦреЗрдВ (рдпрджрд┐ рдпрд╣ рдПрдХ рдЖрдВрддрд░рд┐рдХ рддреНрд░реБрдЯрд┐ рд╣реИ)
- рдПрдХ рд╕рдорд╕реНрдпрд╛ рдХреА рд░рд┐рдкреЛрд░реНрдЯ рдХрд░реЗрдВ (рдХреНрд▓рд┐рдкрдмреЛрд░реНрдб рдкрд░ рд╕реНрдЯрд┐рдХ рдЙрдбрд╝ рдЬрд╛рддрд╛ рд╣реИ, рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╡рд╛рдВрдЫрд┐рдд рд╡рд┐рд╖рдп рдореЗрдВ рдбрд┐рд╕реНрдХ рд╕рд░реНрд╡рд░ рдкрд░ рдЬрд╛рддрд╛ рд╣реИ)
- рдПрдХ рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреЛ рдирд┐рд░рд╕реНрдд рдХрд░реЗрдВ