3

当我从 Visual C++ 以发布模式运行我的应用程序时,出现以下异常。

未处理的异常:System.AccessViolationException:试图读取或写入受保护的内存。这通常表明其他内存已损坏。在 _cexit() 在 .LanguageSupport._UninitializeDefaultDomain(Void * cookie) 在 .LanguageSupport.UninitializeDefaultDomain() 在 .LanguageSupport.DomainUnload(对象源,Eve ntArgs 参数) 在 .ModuleUninitializer.SingletonDomainUnload(Objec t 源,EventArgs 参数)

这不会在调试模式下发生。最初,我在家用计算机上看到了这个异常,但在工作计算机上却没有。当我继续在我的工作计算机上开发时,我最终碰到了它。

另外,我发现当我添加三个 const std::string 变量时,抛出了异常。如果我删除然后一切顺利。

另一条信息:我发现在发布模式下关闭所有编译器优化会使异常消失

一些可疑的事情正在发生。关于如何追踪这一点的任何想法?

谢谢你的帮助,乔

4

7 回答 7

3

乔,你有内存泄漏

您可能正在尝试使用一些已删除的内存。

有关内存泄漏的常见原因以及如何识别它们,请参阅本文,否则,搜索“C++ 内存分析器”+您的编译器/平台,它将提供适合您的编译器和平台的内存分析器的链接,这些将有助于跟踪通过观察程序在运行时如何使用内存来减少内存泄漏。

希望这可以帮助。

编辑

如何追踪它?这不是我的想法,在其他地方可能有更好的建议。. .

找到代码崩溃的地方,它会在访问某个指针的内容(或删除指针)时发生。问题是该指针要么 a) 从未被分配 b) 已被删除。遍历对该类型指针的所有引用,它们是否用于复制 ctors/赋值运算符?

如果是这样,是它的内容被复制还是只是指针?如果只是指针,那么包含类是否试图删除指针?如果是这样,第一个死掉的类将成功,第二个将引发访问冲突。

如果您没有显式编码复制 ctors 和 operator=,那么您应该隐藏它们(声明私有原型但不实现它们),这会阻止编译器为您生成默认实现。

当你隐藏它们时,你会在使用它们的任何地方得到编译器错误,可能是你可以清理它们,或者你需要为每个类实现复制 ctor 和 operator=。

我从明天或两周开始休假,如果您对此有任何疑问,请今天直接给我发电子邮件(点击我的 SO 用户页面上的链接)。

于 2009-07-02T15:18:05.740 回答
2

您是否有任何 #defined 用于在您的代码中进行调试的代码?

IE

#ifndef _DEBUG
   //release only code such as liscensing code
#endif

这是可能导致问题的一件事,我之前也遇到过。

另一种可能性是 VS 问题(或您正在使用的任何 IDE)。尝试直接运行release .exe而不是通过开发环境,看看你是否仍然有同样的问题。

于 2009-07-02T15:14:10.227 回答
1

可以这么说,自从我“愤怒地”完成 C++ 以来已经有一段时间了,所以我在下面所说的一些(或实际上全部)很可能已经过时了。

您是否使用托管 C++?如果不是,那么它听起来像一个未初始化的指针。过去的情况是,所有指针在调试中都为空,我记得关于关闭此行为的一些事情,但我现在不记得完整的细节。

字符串是否超出了它们的变量?不太可能使用 std::string,但值得消除。

于 2009-07-02T15:16:40.517 回答
1

几种可能性:

我猜你正在读/写本地数组结束。在调试版本中,这可能会起作用,因为内存分配不紧密。在发布版本中,这更有可能导致问题,这取决于在数组旁边分配的内容。

另一种可能性是您在某处有一个未初始化的指针。VC 默认在调试模式下初始化局部变量,而不是在发布模式下。因此代码如下:

int* p;
if (p != NULL) { /* do something */ }

通常在发布模式下失败。

于 2009-07-02T15:52:44.760 回答
0

该错误消息强烈表明您有内存问题,可能会覆盖内存。这些很难找到,但您可以通过谷歌搜索“visual c++ memory corruption tool”找到一些可能的解决方案。

内存损坏的问题在于它是不可预测的。它不一定有任何后果,如果有,它们可能不会导致崩溃。像那样崩溃很好,因为它告诉你你遇到了问题。

摆弄调试与发布、添加或删除部分代码、更改优化选项等不太可能解决问题。即使是这样,如果进行任何更改,它也可能会突然出现。

因此,您遇到了内存损坏问题。这些几乎总是很难找到,但有工具。你需要解决这个问题。

你也可以看看你的商店做法。您是否使用不太安全的构造(例如,new数组而不是vector<>)?您是否有编码标准来尝试降低风险?你有代码审查吗?内存损坏可能是阴险的和破坏性的,您希望尽可能避免它。

于 2009-07-02T16:04:31.393 回答
0

您得到的是操作系统的系统异常。这些没有被处理,因为它们不是 C++ 异常。但是,您可以将其转换为 C++ 异常并像普通异常一样捕获它们。

这里有一篇很棒的文章http://www.thunderguy.com/semicolon/2002/08/15/visual-c-exception-handling/(第 3 页)展示了如何创建一个将捕获异常的 Windows Exception 类使用该_set_se_translator方法并引发 C++ 异常。最棒的是您可以从 EXCEPTION_RECORD 结构中获得一个堆栈,尽管您必须添加该功能来处理该结构,但这将有助于缩小您对访问冲突的搜索范围。

于 2009-07-02T17:02:03.263 回答
0

我认为这里的问题是未初始化的局部变量。在调试模式下,变量通常会被初始化,并且不会出现任何异常。但是因此在发布模式下可能会出现错误。

尝试寻找其访问可能导致异常的未初始化变量。

假设您有布尔局部变量。

bool bRet;

在调试版本中,bRet 将被初始化为 0,并且您的代码可以正常工作。

但是在发布时它不会是 0 ,它会是一些随机值,并且您的代码可能正在基于 bRet 执行某些操作。它稍后可能会导致异常,因为 bRet 值是错误的。

于 2009-07-03T10:15:09.770 回答