Difference in behavior between MSVC 2010 compiled Application and MSVC 2019 compiled Application

0

I am working on an MFC Application. We recently migrated the Application from using MSVC 2010 compiler (v100 Toolset) to using MSVC 2019 compiler (v142 Toolset). After the upgrade to MSVC 2019, we are seeing one difference in the behavior of our Application.

In the Application compiled using MSVC 2010 compiler (v100 Toolset), when the main window of the Application is closed, the Application starts the exit process by calling OnClose() function of Main frame window class. During the destruction sequence, we have logging code in the destructor of one of the classes that actually ends up derefencing a dangling pointer (this pointer points to an instance of logging class and the line causing the access violation is attempting to call a function on this logging class instance which has already been destroyed earlier). When this access violation occurs, I can see in the Visual Studio 2010 output window the message "First-chance exception at in the :0xC0000005:Access violation at location ". We don’t have any catch block in this particular call hierarchy to catch this access violation exception and hence we expect the Application to terminate. After pressing F10 (to see if I can move to the next line), call stack shown at this point is as shown below:

exe_name!’class_name::function_name’::’1’::catch$0() Line line_no

Msvcr100.dll!_CallSettingFrame() Line 44

Msvcr100.dll!_CxxCallCatchBlock(_EXCEPTION_RECORD * pExcept) Line 1337

When I debug and press F10, I am able to proceed past the line which caused the access violation. It appears as if runtime is suppressing the exception (or catching it somehow) because I am able to proceed past the line which caused the access violation. Can anyone please explain as to why the application is proceeding even after there is an unhandled exception.

We have chosen the compiler option “Yes with SEH Exceptions (/EHa)” for “C/C++ -> Code Generation -> Enable C++ Exceptions” in project properties of the exe for both VC 10 and VC 19.

In the Application compiled using MSVC 2019 compiler (v142 Toolset), the exact same line of code causes a pure virtual function call to be detected by the runtime and the Application crashes. It is this difference in behavior (between MSVC 2010 compiled Application and MSVC 2019 compiled Application) that I would like to understand.

I do know that dereferencing a dangling pointer will cause undefined behavior. But, I am not able to understand as to how in the VC 2010 compiled Application, I am able to debug (or proceed) past the line which is causing an access violation exception (which has not been handled).

c++
visual-studio-2010
asked on Stack Overflow May 21, 2020 by Raghavendra

1 Answer

1

Welcome to the weird world of Undefined Behavior where literally anything can happen (okay, maybe not anything, but a lot of bad things can happen).

I do know that dereferencing a dangling pointer will cause undefined behavior. But, I am not able to understand as to how in the VC 2010 compiled Application, I am able to debug (or proceed) past the line which is causing an access violation exception (which has not been handled).

The point is it has no explanation. Or rather, the fact that it is Undefined Behavior is itself the explanation. Once you have Undefined Behavior in your program, all bets are off. It very well could work and just move on past the line. On the other hand, it could crash. You never really now which one you'll get.

This is precisely why you shouldn't have Undefined Behavior in your program. You can't guarantee that it will work on every implementation, or even the same implementation sometimes for that matter. Sometimes the compiler will choose to optimize things differently and cause your previously working code to crash. So it's usually best avoided.

As to why it did so in this case, Microsoft very well may have changed their implementation in a way that adversely affected your ability to do this without crashing. But what it is specifically, I couldn't tell you. I have no real way on knowing without knowing what Microsoft does in their implementation, as well as a concrete example of what you're doing in your code.

My advice is since you already seem to know where the error is coming from, just simply find a way to make sure you don't deference the pointer after it's destroyed. That way you can be sure it will work no matter which compiler you use.

answered on Stack Overflow May 21, 2020 by Chipster

User contributions licensed under CC BY-SA 3.0