2010-01-29 33 views
5

Tôi có một ứng dụng dựa trên hộp thoại MFC được tạo bằng MSVS2005. Đây là vấn đề của tôi từng bước. Tôi có nút khi nhấp handler thoại và tương ứng của tôi với mã như thế này:OpenGL ngăn chặn ngoại lệ trong ứng dụng dựa trên hộp thoại MFC

int* i = 0; 
*i = 3; 

Tôi đang chạy phiên bản debug chương trình và khi tôi nhấp vào nút, Visual Studio sản lượng đánh bắt tập trung và cảnh báo "Truy cập viết vi phạm vị trí "ngoại lệ, chương trình không thể phục hồi từ lỗi và tất cả những gì tôi có thể làm là dừng gỡ lỗi. Và đây là hành vi đúng đắn.

Bây giờ tôi thêm một số mã OpenGL khởi trong phương pháp OnInitDialog():

HDC DC = GetDC(GetSafeHwnd()); 
    static PIXELFORMATDESCRIPTOR pfd = 
    { 
     sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd 
     1, // version number 
     PFD_DRAW_TO_WINDOW | // support window 
     PFD_SUPPORT_OPENGL | // support OpenGL 
     PFD_DOUBLEBUFFER, // double buffered 
     PFD_TYPE_RGBA, // RGBA type 
     24, // 24-bit color depth 
     0, 0, 0, 0, 0, 0, // color bits ignored 
     0, // no alpha buffer 
     0, // shift bit ignored 
     0, // no accumulation buffer 
     0, 0, 0, 0, // accum bits ignored 
     32, // 32-bit z-buffer 
     0, // no stencil buffer 
     0, // no auxiliary buffer 
     PFD_MAIN_PLANE, // main layer 
     0, // reserved 
     0, 0, 0 // layer masks ignored 
    }; 

    int pixelformat = ChoosePixelFormat(DC, &pfd); 
    SetPixelFormat(DC, pixelformat, &pfd); 

    HGLRC hrc = wglCreateContext(DC); 
    ASSERT(hrc != NULL); 
    wglMakeCurrent(DC, hrc); 

Tất nhiên đây không phải là chính xác những gì tôi làm, nó là phiên bản đơn giản hóa của mã của tôi. Vâng bây giờ những điều kỳ lạ bắt đầu xảy ra: tất cả khởi tạo là tốt, không có lỗi trong OnInitDialog(), nhưng khi tôi nhấp vào nút ... không có ngoại lệ được ném. Chẳng có gì xảy ra. Ở tất cả. Nếu tôi đặt điểm ngắt tại số *i = 3; và nhấn F11, chức năng xử lý tạm dừng ngay lập tức và lấy nét được trả về ứng dụng, nó tiếp tục hoạt động tốt. Tôi có thể nhấp vào nút một lần nữa và điều tương tự sẽ xảy ra.

Có vẻ như ai đó đã xử lý xảy ra ngoại trừ vi phạm quyền truy cập và thực hiện trả lại âm thầm vào chu kỳ nhận tin nhắn ứng dụng chính.

Nếu tôi nhận xét dòng wglMakeCurrent(DC, hrc);, tất cả hoạt động tốt như trước đây, ngoại lệ được ném và Visual Studio bắt nó và hiển thị cửa sổ có thông báo lỗi và chương trình phải được chấm dứt sau đó.

Tôi gặp sự cố này trong Windows 7 64 bit, NVIDIA GeForce 8800 với trình điều khiển mới nhất (trong 11,11/2010) có sẵn tại trang web được cài đặt. Đồng nghiệp của tôi có Windows Vista 32-bit và không có vấn đề như vậy - ngoại lệ được ném và ứng dụng bị treo trong cả hai trường hợp.

Vâng, hy vọng chàng trai tốt sẽ giúp tôi :)

PS Vấn đề ban đầu nơi đăng theo this chủ đề.

+0

Thật buồn cười, tôi đã gặp vấn đề tương tự gần đây ... nếu bạn bọc mã ngoại lệ trong khối try-catch, nó sẽ bắt ngoại lệ có, nhưng nếu ngoại lệ lan truyền trong mã MFC nó dường như bị nuốt chửng. Tôi đoán một cách giải quyết tiềm năng là sử dụng các khối try-catch cho chính mình. – AshleysBrain

+0

Tôi có thể xác nhận vấn đề này và nó đã làm với OpenGL trên windows vista 64 bit và cửa sổ 7 64 bit. Đang tìm kiếm câu trả lời cho bản thân mình :) – ralphtheninja

+0

Điều này có vẻ tương tự như vấn đề của tôi: http://stackoverflow.com/questions/2622200/exceptions-silently-caught-by-windows-how-to-handle-manually –

Trả lời

3

Ok, tôi đã tìm hiểu thêm một số thông tin về điều này. Trong trường hợp của tôi là các cửa sổ 7 cài đặt KiUserCallbackExceptionHandler là trình xử lý ngoại lệ, trước khi gọi WndProc của tôi và cho tôi kiểm soát thực thi. Điều này được thực hiện bởi ntdll! KiUserCallbackDispatcher. Tôi nghi ngờ rằng đây là một biện pháp an ninh được thực hiện bởi Microsoft để ngăn chặn hack vào SEH.

Giải pháp là bọc wndproc (hoặc hookproc) bằng khung thử/ngoại trừ để bạn có thể nắm bắt ngoại lệ trước khi Windows thực hiện.

Nhờ Skywing tại http://www.nynaeve.net/

Chúng tôi đã liên lạc với nVidia về vấn đề này, nhưng họ nói nó không phải là lỗi của họ , mà là của Microsoft. Có thể bạn vui lòng cho biết cách bạn đặt trình xử lý ngoại lệ không? Và bạn có một số thông tin bổ sung hay không, ví dụ: một số phản hồi từ Microsoft?

Tôi đã sử dụng "! Exchain" -command trong WinDbg để nhận thông tin này.

+0

Chúng tôi đã liên lạc với nVidia về vấn đề này, nhưng họ nói đó không phải là lỗi của họ, mà là của Microsoft. Bạn có thể vui lòng cho biết cách bạn đặt trình xử lý ngoại lệ không? Và bạn có một số thông tin bổ sung không, ví dụ: một số phản hồi từ Microsoft? – Mikhail

+0

SEH là câu trả lời thuận tiện nhất, vì vậy tôi sẽ chấp nhận nó. – Mikhail

0

Đầu tiên, cả hai hành vi đều chính xác. Dereferencing một con trỏ null là "hành vi không xác định", không phải là một vi phạm truy cập được bảo đảm.

Trước tiên, hãy tìm hiểu xem điều này có liên quan đến việc ném ngoại lệ hoặc chỉ để truy cập vị trí bộ nhớ không (thử ngoại lệ khác).

Nếu bạn định cấu hình Visual Studio để dừng vi phạm quyền truy cập đầu tiên, nó có bị hỏng không?

Gọi VirtualQuery (NULL, ...) trước và sau glMakeCurrent và so sánh. Có lẽ trình điều khiển nVidia OpenGL VirtualAlloc page zero (một ý tưởng tồi, nhưng không phải là không thể hoặc bất hợp pháp).

+0

Hành vi tương tự cho bất kỳ ngoại lệ, bao gồm cả thủ công được nâng lên bằng toán tử ném. Nếu tôi cấu hình Visual Studio để dừng lại trên trường hợp ngoại lệ cơ hội đầu tiên, nó phá vỡ. – Mikhail

+0

Âm thanh như một bộ xử lý ngoại lệ vectơ được đăng ký và ăn ngoại lệ. http://msdn.microsoft.com/en-us/library/ms681420(VS.85).aspx Phá vỡ ngoại lệ cơ hội đầu tiên, sau đó bắt đầu một bước (đảm bảo bạn có tùy chọn "Chỉ Mã của tôi "bị vô hiệu hóa để bạn có thể duyệt qua các thư viện khác). Có lẽ một số trình xử lý trả về EXCEPTION_CONTINUE_EXECUTION thay vì EXCEPTION_CONTINUE_SEARCH. –

+0

So sánh kết quả của VirtualQuery (NULL, ...), kết quả giống nhau cho các cuộc gọi trước và sau wglCreateContext(). – Mikhail

1

Thay vì gói các WndProc hoặc hooking tất cả WndProcs, bạn có thể sử dụng vector Xử lý ngoại lệ:

http://msdn.microsoft.com/en-us/library/ms679274.aspx

+0

Tôi đã làm điều này, và nó đã làm việc cho tôi. – Brian

+0

Tôi lấy lại. Chúng tôi đã phải hoàn nguyên thay đổi này bởi vì nó quá hung hăng. Có những ngoại lệ mà chúng tôi muốn để lại một mình và cho phép bị xử lý theo cách thông thường, nhưng chúng tôi không thể phân biệt chúng với Vi phạm Truy cập và những thứ tương tự mà chúng tôi muốn gặp phải. – Brian

+0

Tôi có một lớp cơ sở cho tất cả giao diện người dùng ghi đè WndProc với __try/__catch. Trình xử lý sau đó gọi trình báo cáo sự cố trong bản phát hành, khi gỡ lỗi nó tiếp tục để chúng tôi có thể gỡ lỗi sự cố. –

0

Tôi đã tìm thấy câu hỏi này khi tôi đang xem xét một vấn đề tương tự. Vấn đề của chúng tôi hóa ra là im lặng tiêu thụ ngoại lệ khi chạy một ứng dụng 32 bit trên Windows 64 bit.

http://connect.microsoft.com/VisualStudio/feedback/details/550944/hardware-exceptions-on-x64-machines-are-silently-caught-in-wndproc-messages

Có một sửa chữa có sẵn từ Microsoft, mặc dù triển khai nó là hơi khó khăn nếu bạn có nhiều nền tảng mục tiêu:

http://support.microsoft.com/kb/976038

Dưới đây là một bài viết về đề tài này mô tả hành vi:

http://blog.paulbetts.org/index.php/2010/07/20/the-case-of-the-disappearing-onload-exception-user-mode-callback-exceptions-in-x64/

Chủ đề này trên ngăn xếp tràn cũng mô tả vấn đề tôi đã trải qua: Exceptions silently caught by Windows, how to handle manually?

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