Menampilkan Informasi Pengecualian Sebelum Keluar Darurat

Kenapa dan untuk apa


Selama pengembangan, hal-hal tidak selalu mulus. Ada masalah yang tidak muncul pada tes, tetapi setelah rilis. Untuk kasus seperti itu, kami membuat sistem kecil untuk menangkap pengecualian dan kesalahan internal.


Tangkapan pengecualian


Agar program sebelum crash dapat memberi tahu kami (di luar debugger) apa masalahnya, Anda dapat menggunakan fungsi pemrosesan sinyal .


Beberapa contoh sinyal seperti itu:


    signal(SIGABRT, abort_handler); //  ,    nullptr   
    signal(SIGFPE, floating_point_handler); //      
    signal(SIGILL, illegal_instruction_handler); //     intrinsics (SSE/AVX/Other) 

Penangan sinyal



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;

    // firstly see if dbghelp.dll is around and has the function we need
    // look next to the EXE first, as the one in System32 might be old
    // (e.g. Windows 2000)
    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)
    {
        //  dbgHelp 
        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);

            //    : App Name, User Name, Time, Ext
            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;

                //  Dump 
                MINIDUMP_TYPE dump_flags = MINIDUMP_TYPE(MiniDumpNormal | MiniDumpFilterMemory | MiniDumpScanMemory);

                //   
                char* logFileContent = nullptr;
                DWORD logFileContentSize = 0;

/////////////////////////////////////
                //        (logFileContent)
/////////////////////////////////////

        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;
}


, , (, , ), , :
gambar
C# + WPF,


:


  • Lanjutkan eksekusi program (jika ini adalah kesalahan internal)
  • Laporkan masalah (tumpukan terbang ke clipboard, pengguna pergi ke server perselisihan dalam topik yang diinginkan)
  • Batalkan program

Source: https://habr.com/ru/post/undefined/


All Articles