【问题标题】:Difference in behavior between MSVC 2010 compiled Application and MSVC 2019 compiled ApplicationMSVC 2010 编译的应用程序和 MSVC 2019 编译的应用程序之间的行为差​​异
【发布时间】:2020-05-21 06:27:41
【问题描述】:

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

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

exe_name!'class_name::function_name'::'1'::catch$0() Line 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 编译的应用程序中如何调试(或继续)导致访问冲突异常(尚未处理)的行。

【问题讨论】:

  • 欢迎来到 Stack Overflow!
  • 您甚至可能会在同一个编译器上看到不同的行为,但优化级别不同。正如您所说,取消引用空指针是未定义的行为。这意味着编译器在生成机器代码时可以假设这永远不会发生。不同级别的优化可以(并且经常这样做)生成导致 UB 表现不同的机器代码。见鬼,即使在调试器的监督下运行程序也会导致 UB 表现不同。

标签: c++ visual-studio-2010


【解决方案1】:

欢迎来到 literally anything can happen 的怪异未定义行为世界(好吧,也许没什么,但可能会发生很多坏事)。

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

关键是它没有解释。或者更确切地说,它是未定义行为的事实本身就是解释。一旦你的程序中有未定义的行为,所有的赌注都没有了。它可以很好地工作,然后继续前进。另一方面,它可能会崩溃。你永远不会真正知道你会得到哪一个。

这正是您不应该在程序中使用未定义行为的原因。您不能保证它适用于每个实现,或者有时甚至是相同的实现。有时编译器会选择以不同的方式优化事物并导致您之前工作的代码崩溃。所以通常最好避免。

至于为什么在这种情况下这样做,微软很可能已经改变了他们的实施方式,从而对您在不崩溃的情况下执行此操作的能力产生了不利影响。但具体是什么,我不能告诉你。如果不知道 Microsoft 在他们的实现中做了什么,以及你在代码中所做的具体示例,我就无法真正知道。

我的建议是,既然您似乎已经知道错误的来源,只需找到一种方法来确保您在指针被销毁后不会对其进行顺从。这样,无论您使用哪种编译器,您都可以确保它可以正常工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-17
    • 1970-01-01
    • 2018-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多