Visual studio 2008 Windows 7 Visual C++ 2008 Strange Seg Fault and Null Pointer behavior

Visual studio 2008 Windows 7 Visual C++ 2008 Strange Seg Fault and Null Pointer behavior,visual-studio-2008,visual-c++,windows-7,transactions,segmentation-fault,Visual Studio 2008,Visual C++,Windows 7,Transactions,Segmentation Fault,By the time our development machines have been upgraded to windows 7 something strange started to happen. When our program (visual c++ 2008, some owl to mfc adapter, sql server 2008r2) accesses for example a null pointer it does not crash as expected but it goes on running just closing the actual window. Might be a good idea, but this makes database-transaction handling a nightmare. In case of a hidden crash in the program a started transaction with uncommitted changes is remaining opened and th

By the time our development machines have been upgraded to windows 7 something strange started to happen. When our program (visual c++ 2008, some owl to mfc adapter, sql server 2008r2) accesses for example a null pointer it does not crash as expected but it goes on running just closing the actual window. Might be a good idea, but this makes database-transaction handling a nightmare. In case of a hidden crash in the program a started transaction with uncommitted changes is remaining opened and the user is able to go on using the program. When the next transaction gets committed normally, the changes "hanging" in the first half completed transaction are saved too. This is definitely not intended and leads to data corruption.

Before Windows 7 we didn't care about that, a crash was a crash. Program was closed, all transactions running were rolled back.

What can we do to switch back to the old behavior?


#1

You can have your own unhandled exception routine to catch segfaults/access violations.

// global scope
    bool in_region_of_interest(_EXCEPTION_POINTERS *ep) {
        // TODO: Check if you aren't breaking some 3rd party functionality by exiting now.
        return ep && ep->ExceptionRecord; // Pretty much a stub.
    }
    static const bool  feelin_gentle = false; // Do we care for semi-clean exits?
    static const DWORD min_virt_rng  = 0x1000; // max virtual address that 'indicates' null ptr access.
    LONG WINAPI my_unh_exc_hndlr(_EXCEPTION_POINTERS *excPtrs)
    {
        if (in_region_of_interest(excPtrs)) {
           DWORD code = excPtrs->ExceptionRecord->ExceptionCode;
           if (EXCEPTION_ACCESS_VIOLATION == code && // If fingers burn in fire.
              min_virt_rng > excPtrs->ExceptionRecord->ExceptionInformation[1]) { // If it was a *(void*)0 that we accessed.
              if (feelin_gentle)
                 ExitProcess(code);
              else
                 TerminateProcess(GetCurrentProcess(), code);
           }
        }
        return EXCEPTION_CONTINUE_SEARCH; // Give control to the next filter.
    }

// ... somewhere in the beginning of main()
    SetUnhandledExceptionFilter(my_unh_exc_hndlr);

The reason you SHOULDN'T always crash is that some dependencies might depend on being able to handle a segfault. You should use a mechanism to dynamically switch this feature on or off, depending on where you expect a crash. Unless you are really sure it won't get broken, it's better to ignore everything except invalid access at address of or around 0. I took a value if 0x1000 out of my ass, as I won't expect any offset in an object be larger than that in my program.

Extra info: http://msdn.microsoft.com/en-us/library/windows/desktop/aa363082(v=vs.85).aspx


#2

Why not just fix the crashes? A crash is a sign that something is seriously wrong, maybe the problem has other side-effects besides the crash?

#3

I see the problem in production. When it crashes on the customers machine. With the actual behavior the customer does not even know that he crashed. The dialog he was using just disappears. As if everything has been successful.

#4

I would say that is a terrible user interface design. A user should always know if an action he or she did was successful or not.

#5

I totally agree that from a users perspective an unhandled crash is not an acceptable solution. But this way it worked with the same product (same build) on windows vista and before. Let me stress, that really the same build acts different just by running it on another OS. Maybe we are total idiots here and do everything wrong, but we are in business for a long time and we do a lot of number crunching that depends on database transactions to work correctly and at least until windows 7 we could be sure, that a crash terminates the program and the transaction is rolled back.