MSVC 2010编译的应用程序与MSVC 2019编译的应用程序之间的行为差 异

问题描述 投票:0回答:1

我正在开发MFC应用程序。我们最近将应用程序从使用MSVC 2010编译器(v100 Toolset)迁移到使用MSVC 2019编译器(v142 Toolset)。升级到MSVC 2019后,我们发现我们的应用程序的行为有所不同。

在使用MSVC 2010编译器(v100 Toolset)编译的应用程序中,当关闭应用程序的主窗口时,应用程序通过调用Main frame窗口类的OnClose()函数启动退出过程。在销毁序列期间,我们在一个类的析构函数中记录了日志代码,该类的析构函数实际上最终取消了悬空指针的指针(此指针指向日志记录类的实例,并且导致访问冲突的行正在尝试对此接口调用函数日志类实例,该实例之前已被销毁)。发生此访问冲突时,我可以在Visual Studio 2010输出窗口中看到消息“位置0xC0000005:访问冲突中的第一次机会异常”。在此特定的调用层次结构中,我们没有任何catch块来捕获此访问冲突异常,因此我们希望该应用程序终止。按F10键(看是否可以移至下一行)后,此时显示的调用堆栈如下所示:

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

Msvcr100.dll!_CallSettingFrame()第44行

[Msvcr100.dll!_CxxCallCatchBlock(_EXCEPTION_RECORD * pExcept)第1337行]

当我调试并按F10键时,我可以越过导致访问冲突的行。似乎运行时正在抑制该异常(或以某种方式捕获该异常),因为我能够继续执行导致访问冲突的行。任何人都可以解释为什么即使有未处理的异常,申请仍在继续进行。

我们在VC 10和VC 19的exe的项目属性中为“ C / C ++->代码生成->启用C ++异常”选择了“具有SEH异常(/ EHa)的编译器选项”。

在使用MSVC 2019编译器(v142工具集)编译的应用程序中,完全相同的代码行导致运行时检测到纯虚拟函数调用,并且应用程序崩溃。我想了解的是这种行为上的差异(在MSVC 2010编译的应用程序和MSVC 2019编译的应用程序之间)。

我确实知道取消引用悬空指针将导致未定义的行为。但是,我无法理解在VC 2010编译的应用程序中如何调试(或继续)经过导致访问冲突异常(尚未处理)的行。

c++ visual-studio-2010
1个回答
1
投票

欢迎来到literally anything can happen的不可思议行为的怪异世界(好吧,也许什么也不是,但是可能发生很多坏事)。

我确实知道取消引用悬空指针将导致未定义的行为。但是,我无法理解在VC 2010编译的应用程序中如何调试(或继续)经过导致访问冲突异常(尚未处理)的行。

关键是它没有解释。更确切地说,它是未定义行为的事实本身就是解释。一旦您的程序中有未定义的行为,所有的赌注都将关闭。它可以很好地工作,并且可以继续前进。另一方面,它可能会崩溃。您现在从未真正获得过。

这就是为什么您的程序中不应出现未定义行为的原因。您不能保证它可以在每个实现上使用,有时甚至不能在同一实现上使用。有时,编译器会选择以不同的方式优化事物,从而导致您以前的工作代码崩溃。因此通常最好避免。

关于在这种情况下这样做的原因,Microsoft很有可能已经改变了其实现方式,从而对您执行此功能的能力产生了不利影响而不会崩溃。但是具体是什么,我无法告诉你。在没有不知道微软在其实现中所做的工作以及关于您在代码中正在执行的具体示例的过程中,我没有真正的方法。

我的建议是,因为您似乎已经知道错误的出处,所以只需简单地找到一种方法,以确保在指针被销毁后不遵循该指针。这样,您可以确保无论使用哪种编译器,它都可以工作。

© www.soinside.com 2019 - 2024. All rights reserved.