Catching access violations on Windows

与世无争的帅哥 提交于 2019-12-08 21:57:37

问题


I am trying to catch all unhandled exceptions in my application so I can save a log file when they occurr. This is a 64-bit Windows application compiled using Visual Studio 2013, written in C++. For testing I am using the default C++ Win32 project generated by VS.

I am catching all exceptions by registering a handler using SetUnhandledExceptionFilter. This works fine for /most/ cases, but not all. All throw()-n exceptions are caught, and most hardware exceptions like floating point or access violations as well. The code that doesn't trigger the handler is:

std::vector<int> foo(5, 0);
for (auto& f : foo)
    foo.erase(foo.begin() + 1);

Instead I just get the standard windows crash dialog box, without my exception handler getting called. If I run it in Visual Studio with debugger attached however, it correctly reports an access violation exception. Other types of access violations trigger the handler as well:

float* ptr = nullptr;
float value = *ptr;

Code above triggers the exception handler.

I have tried using try/catch or catching SIGSEGV signal too, but neither get triggered with the first example. abort/terminate signals don't get called either. In short I am in no way notified when that crash happens.

I want to know is there any way I can get some kind of a notification in my application before it crashes due to the access violation caused by the first example? Since VS seems to be able to detect it I'm assuming there's a way.

EDIT: I just want to make it clear I'm running the code in release mode and the error in the first example isn't caused by iterator out of bounds check done in debug mode.

EDIT2: I included the simplest example I can come up with using a win32 console app. See it here: http://pastebin.com/8L1SN5PQ

Make sure to run it in release mode with no debugger attached.


回答1:


These kind of runtime errors are handled differently, they don't produce an SEH exception. Roughly classified somewhere between "programming bug" and "malware attack". And about as informative as a uncaught C++ exception if you don't have a debugger attached, the default handler invokes instant death with __fastfail().

You'll have to call _set_invalid_parameter_handler() in your main() function to alter the way they are handled. You could throw a C++ exception in your custom handler or call RaiseException() to trigger your catch-em-all handler or just report them right there. Favor the latter, you want to ensure that the process is always terminated.

Do beware that your snippet is not the best possible example. This is UB when you build your program without iterator debugging enabled, like the Release build with default settings. UB does not guarantee you'll get an SEH exception. And if it does then you'll have to write your exception filter very carefully, it will be called with the heap lock still taken so basic stuff cannot work. Best way is to wakeup a guard process with a named event. Which then takes a minidump and terminates the program.




回答2:


You are not seeing the exception because it is being handled internally by the C runtime. Specifically it's a bounds check not an access violation.

Running it up in the debugger I find that it is line 242 in vector:

            _DEBUG_ERROR("vector iterators incompatible");

Which ultimately calls _CrtDebugReportW: https://msdn.microsoft.com/en-us/library/8hyw4sy7.aspx

You can control the behaviour of _CrtDebugReportW using _CrtSetReportMode.

Note that this has no effect in release mode as these are debug-mode bounds checks.



来源:https://stackoverflow.com/questions/33037202/catching-access-violations-on-windows

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!