2011-01-31 21 views
11

Tôi đang sử dụng đoạn mã sau để tạo ra một tập tin minidump bất cứ khi nào có một ngoại lệ có cấu trúc được tạo ra từ mã của tôi:Tạo minidump cho ngoại lệ truy cập vi phạm sử dụng SetUnhandledExceptionFilter()

void CreateMiniDump(EXCEPTION_POINTERS* pep) 
{ 
    // Open the file 
typedef BOOL (*PDUMPFN)( 
    HANDLE hProcess, 
    DWORD ProcessId, 
    HANDLE hFile, 
    MINIDUMP_TYPE DumpType, 
    PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, 
    PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, 
    PMINIDUMP_CALLBACK_INFORMATION CallbackParam 
); 


    HANDLE hFile = CreateFile(_T("C:/temp/MiniDump.dmp"), GENERIC_READ | GENERIC_WRITE, 
    0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 

    HMODULE h = ::LoadLibrary(L"DbgHelp.dll"); 
    PDUMPFN pFn = (PDUMPFN)GetProcAddress(h, "MiniDumpWriteDump"); 

    if((hFile != NULL) && (hFile != INVALID_HANDLE_VALUE)) 
    { 
    // Create the minidump 

    MINIDUMP_EXCEPTION_INFORMATION mdei; 

    mdei.ThreadId   = GetCurrentThreadId(); 
    mdei.ExceptionPointers = pep; 
    mdei.ClientPointers  = TRUE; 

    MINIDUMP_TYPE mdt  = MiniDumpNormal; 

    BOOL rv = (*pFn)(GetCurrentProcess(), GetCurrentProcessId(), 
     hFile, mdt, (pep != 0) ? &mdei : 0, 0, 0); 



    // Close the file 

    CloseHandle(hFile); 

    } 

} 

LONG WINAPI MyUnhandledExceptionFilter(
struct _EXCEPTION_POINTERS *ExceptionInfo 
) 
{ 
    CreateMiniDump(ExceptionInfo); 
    return EXCEPTION_EXECUTE_HANDLER; 
} 

Và tôi đang làm SetUnhandledExceptionFilter(MyUnhandledExceptionFilter); từ chính điểm vào của ứng dụng của tôi (tôi không thiết lập nó cho mỗi thread mặc dù). Sau này để kiểm tra mã này tôi đã làm như sau để tạo ra một sự vi phạm truy cập: int* p = 0; *p = 0; Tệp kết xuất đã được tạo. Sau đó, tôi đã sử dụng windbg và mở tệp kết xuất và sử dụng lệnh .ecxr để nhận được bản ghi ngoại lệ. Tuy nhiên, không có thông tin nào đến đó (tức là tôi không nhận được ngăn xếp cuộc gọi). Ngoài ra nếu tôi sử dụng lệnh !analyze -v thì nó có thể hiển thị dòng nơi xảy ra sự cố. Có ai biết những gì tôi đang thiếu và làm thế nào để giải quyết điều này?

BTW, tôi đang sử dụng trình biên dịch VC7 với cờ/EHa (mô hình ngoại lệ asynchronuos).

+0

Tôi không có câu trả lời cho bạn, nhưng tôi không hoàn toàn chắc chắn rằng 'mdei.ClientPointers' thực sự phải là' TRUE' – Hasturkun

+0

@Hasturkun: Tôi đã thử cả hai, không tạo ra bất kỳ sự khác biệt nào. – Naveen

+1

Lưu ý rằng các trình xử lý được cài đặt bằng cách sử dụng SetUnhandledExceptionFilter(), bởi kinh nghiệm của tôi sẽ không được gọi trong mọi trường hợp. I E.sự cố trong Windows kernel Dll (đôi khi xảy ra rõ ràng) chỉ có thể được báo cáo bằng cách sử dụng Windows Error Reporting. Xem bài viết của tôi "Post Mortem Debuugging revisited" trên DDJ http://www.drdobbs.com/architecture-and-design/227900186 –

Trả lời

2

Mã của bạn tạo minidump là OK, vấn đề là gỡ lỗi sau khi chết. Trình gỡ lỗi phải có quyền truy cập vào mã nguồn của chương trình, tệp .pdb (phải là tệp pdb được tạo khi chương trình thực thi này được xây dựng) và các biểu tượng gỡ lỗi hệ điều hành. Chỉ có tất cả thông tin này, trình gỡ rối có thể hiển thị vị trí ngoại lệ trong mã nguồn và ngăn xếp cuộc gọi.

Quá trình gỡ lỗi sau khi xử lý bằng Trình gỡ lỗi Visual Studio được mô tả chi tiết tại đây: http://www.codeproject.com/KB/debug/postmortemdebug_standalone1.aspx Đối với WinDbg, sử dụng đường dẫn Tệp, Nguồn và Hình ảnh để cung cấp thông tin tương tự cho trình gỡ lỗi.

+1

Cảm ơn bạn đã trả lời các tệp ..pdb. Cuối cùng quản lý để theo dõi vấn đề, nó đã được gây ra như là một trong nhiều dll trong ứng dụng của tôi đã làm '_set_se_translator' trước khi tôi có thể cài đặt bộ lọc ngoại lệ unhandled. Nếu tôi loại bỏ dịch giả đó, nó hoạt động tốt. – Naveen

+0

Vâng, có chính xác 1 bộ lọc ngoại lệ chưa được xử lý và các mô-đun khác được tự do viết trên máy của bạn - không phải thiết kế rất tốt –

2

Tuy nhiên, không có thông tin sắp có (tức là tôi không nhận được các cuộc gọi stack)

.ecxr không có nghĩa vụ phải in một callstack, nó chỉ phải thiết lập bối cảnh đó của hồ sơ ngoại lệ được lưu trữ - bạn muốn làm một cái gì đó như k 10 để thực sự in nó. Hoặc, vì bạn đang sử dụng WinDBG, hãy mở cửa sổ callstack.

(Có thể bạn đã làm điều này; Tôi không chắc chắn từ mô tả của bạn như thế nào .ecxr không thành công - nó sẽ in một cái gì đó để cho bạn biết nó là gì/không thể làm ...)

Một điều nữa để kiểm tra là bạn đang thực sự nhận được các con trỏ ngoại lệ được truyền vào - mã sẽ tạo ra một bãi chứa mà không có chúng, nhưng bạn sẽ nhận được một callstack sôi nổi theo cách đó.

Bạn đã đề cập đến in a comment on Alex's answer có một số can thiệp từ một DLL ghi đè bộ lọc của bạn bằng thư viện thời gian chạy ... Đây là sự cố thường gặp. Tôi đã có may mắn bằng cách sử dụng the technique described by Oleg Starodumov:

Có một cách tiếp cận khác có thể và dễ thực hiện hơn nhiều so với hai bước trước. Sau khi chúng tôi đã đăng ký bộ lọc riêng của mình, chúng tôi có thể vá phần đầu của hàm SetUnhandledExceptionFilter để nó không thể đăng ký bộ lọc nữa.

Anh ấy cung cấp một số mã ví dụ hữu ích cho mục đích này, đã phục vụ tôi tốt trong những năm qua.

Các vấn đề liên quan