【发布时间】:2016-05-11 13:52:21
【问题描述】:
我的代码在 Release 配置中崩溃,但在 Debug 配置中没有。它只是在我退出程序作为最后一行'return(0);'时才这样做执行。我在 Visual Studio 开发环境中工作,当它崩溃时,VS Studio 为我提供了“调试”代码的选项。当我选择它时,它会导致一个错误对话框弹出:
myapp.exe 中 0x00007FF851A0512D (msvcp120d.dll) 处的未处理异常:0xC0000005:访问冲突读取位置 0xFFFFFFFFFFFFFFFF。
当我在发生此异常时选择“中断”时,它会在 xstring 文件中突出显示以下函数:
void _Free_proxy()
{ // destroy proxy
typename _Alloc::template rebind<_Container_proxy>::other
_Alproxy;
this->_Orphan_all();
_Alproxy.destroy(this->_Myproxy);
_Alproxy.deallocate(this->_Myproxy, 1);
this->_Myproxy = 0;
}
尤其是'_Alproxy.destroy(this->_Myproxy);'这一行被突出显示为罪魁祸首。
我认为问题可能是我的“发布”代码以某种方式链接到“调试”msvcp120d.dll 库,因为它在弹出的第一个对话框中突出显示 - 但这可能只是因为我开始使用 VS 调试器来识别这个问题。但即使这是问题所在,我也不确定如何告诉 VS 使用 msvcp120.dll 编译 Release 配置,使用 msvcp120d.dll 编译 Debug 配置。
(作为记录,我使用发布配置中的“多线程 DLL (/MD)”标志和调试配置中的“多线程调试 DLL (/MDd)”生成我的所有代码)
关键是当发布版本崩溃时,进程进入“暂停”状态,我无法通过任务管理器完全杀死它。然后如果不重新启动计算机,我什至无法重新编译新的 Release 版本!
我不知道如何隔离这个问题。谁能告诉我如何解决这个问题?
更新
这个项目的代码非常大 - 所以将它提炼成一个表现相同行为的最小版本,虽然通常是跟踪错误的有效方法,但将是一项相当大的任务。我希望有一些方法可以记录进程并找出哪个进程正在调用 msvcp120d.dll @Niall,我生成了依赖关系图,它很大。在不泄露任何专有信息的情况下,附上图表的全局视图。
Dependency graph of entire solution
是否有任何工具可以跟踪调用 msvcp120d.dll 的工具?
【问题讨论】:
-
听起来您的代码中有未定义的行为。你可以让minimal reproducible example 展示相同的行为吗?
-
您或您在 msvcp120d.dll(运行时的调试版本)中的一个依赖项链接到发布版本。混合运行时可能会导致这样的问题。要追踪谁,您可以使用 Dependency Walker 列出依赖关系树。
-
msvcp120d.dll 是 Visual Studio 2013 调试 crt 的一部分。如果在发布中使用它,我希望 UB 因为调试和发布运行时彼此不兼容。确保您的应用程序和所有依赖的 dll 都构建在相同的配置中。混合编译器版本也不安全。
-
您的程序正在破坏堆。看到在您的进程中加载的 msvcp120d.dll 实际上可以保证这会发生。像 std::string 这样的基本 C++ 模板类对象在调试和发布版本中没有相同的布局。这不是与 VM 一起运行以确保每个人都同意对象的外观的 Java 或 C#。在 C++ 中,您必须使用完全相同的编译器使用完全相同的设置构建您链接的所有内容,包括不是您自己构建的库。
-
我不认识那个图,但这是我正在谈论的工具。 dependencywalker.com
标签: c++ debugging visual-studio-2013 release