发布模式下的 AccessViolationException (C++)
当我从 Visual C++ 以发布模式运行应用程序时,出现以下异常。
未处理的异常: System.AccessViolationException: 试图读或写保护 记忆。 这通常是一个迹象 其他内存已损坏。 在 _cexit() at .LanguageSupport._UninitializeDefaultDomain(Void * cookie) 在 .LanguageSupport.UninitializeDefaultDomain() 在 .LanguageSupport.DomainUnload(对象 来源,Eve ntArgs 参数)位于 .ModuleUninitializer.SingletonDomainUnload(Objec t 源,EventArgs 参数)
这在调试模式下不会发生。 最初,我在家用计算机上看到了此异常,但在工作计算机上没有看到。 当我继续在工作计算机上进行开发时,我最终遇到了它。
另外,我发现当我添加三个 const std::string 变量时抛出异常。 如果我删除了那么一切都会顺利。
另一条信息:我发现在发布模式下关闭所有编译器优化会使异常消失,
有些可疑的事情正在发生。 关于如何追踪这个问题有什么想法吗?
谢谢您的帮助, 乔
I'm getting the following exception when I run my application in Release mode from Visual C++.
Unhandled Exception:
System.AccessViolationException:
Attempted to read or write protected
memory. This is often an indication
that other memory is corrupt. at
_cexit() at .LanguageSupport._UninitializeDefaultDomain(Void
* cookie) at .LanguageSupport.UninitializeDefaultDomain()
at
.LanguageSupport.DomainUnload(Object
source, Eve ntArgs arguments) at
.ModuleUninitializer.SingletonDomainUnload(Objec
t source, EventArgs arguments)
This doesn't happen in Debug mode. Initially, I saw this exception on my home computer, but not work computer. When I continued to develop on my work computer, I ended up bumping into it.
Also, I found that when I added three const std::string variables the exception was thrown. If I removed then then all went well.
Another piece of information: I've found that turning off all the compiler optimizations in Release mode makes the exception go away
Something fishy is going on. Any ideas on how to track this down?
Thanks for the help,
Joe
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
乔,您有内存泄漏。
您可能正在尝试使用一些已删除的内存。
请参阅本文了解内存泄漏的常见原因以及如何识别它们,否则,搜索“C++内存分析器”+您的编译器/平台,它将提供适合您的编译器和平台的内存分析器的链接,这些将通过观察程序运行时如何使用内存来帮助跟踪内存泄漏。
希望这可以帮助。
编辑
如何追踪它? 这不是我的想法,其他地方可能有更好的建议。 。 。
查找代码崩溃的位置,它是在访问某个指针的内容(或删除指针)时发生的。
问题是该指针 a) 从未被分配 b) 已被删除。
遍历对该类型指针的所有引用,它们是否在复制向量/赋值运算符中使用?
如果是这样,是复制它的内容还是只是复制指针?
如果只是指针,那么包含类是否试图删除指针? 如果是这样,第一个死亡的类将成功,第二个将引发访问冲突。
如果您没有显式编码复制因子和运算符=,那么您应该隐藏它们(声明私有原型但不实现它们),这会阻止编译器为您生成默认实现。
当你隐藏它们时,你会在使用它们的任何地方得到编译器错误,你可能可以清理它们,或者你需要为每个类实现复制构造函数和运算符=。
我从明天或两周开始休假,如果您对此有任何疑问,请立即给我发送电子邮件(点击我的 SO 用户页面上的链接)。
Joe, you have a memory leak.
You're probably trying to use some memory that has been deleted.
See this article for common causes of memory leaks, and how to identify them, otherwise, search for "C++ memory profiler" + your compiler/platform, it'll give links to Memory profilers suitable for your compiler and platform, these will help track down the memory leak by watching how your program uses memory as it runs.
Hope this helps.
EDIT
How to track it down? This is off the top of my head, there may be better advice else where . . .
Find where the code crashes, it'll be when accessing the contents of some pointer (or deleting a pointer).
The problem is that that pointer has either a) never been assigned b) is already deleted.
Go through all references to pointers of that type, are they used in copy ctors/assignment operators?
If so, are it's contents being copied or just the pointer?
If just the pointer then is the containing class trying to delete the pointer? If so the first class to die will succeed, the second will throw an access violation.
If you don't explicitly code copy ctors and operator=, then you should hide them (declare private prototypes but don't implement them), this stops the compiler from generating default implementations for you.
When you hide them you'll get compiler errors everywhere they're being used, it might be that you can clean these up, or that you need to implement the copy ctor and operator= for each class.
I'm on vacation from tomorrow or two weeks, email me direct today (follow the link on my SO user page) if you've any questions on this.
您的代码中是否有#define 的代码可供调试?
即
这是可能导致问题的一件事,我以前也遇到过。
另一种可能性是 VS 问题(或您正在使用的任何 IDE)。
尝试直接运行release.exe而不是通过开发环境,看看是否仍然存在相同的问题。
Do you have any code that is #defined out for debuging in your code?
i.e.
That's one thing that could be causing the problem, and I've run into it before as well.
Another possibility is a VS issue (or whatever IDE you're using).
Try running the release .exe directly instead of through the develoment environment and see if you still have the same issue.
可以说,我已经有一段时间“愤怒地”完成 C++ 了,所以我下面所说的一些(或者实际上全部)内容很可能已经过时了。
您使用托管 C++ 吗? 如果不是,那么它听起来像是一个未初始化的指针。 过去的情况是在 debug & 中所有指针都为空。 我记得有关关闭此行为的一些信息,但我现在不记得完整的细节。
字符串是否超出了它们的变量范围? 对于 std::string 不太可能,但值得消除。
It's a while since I've done C++ "in anger" so to speak, so some (or indeed all) of what I say below may well be out of date.
Are you using managed C++? If not then it sounds like an uninitialised pointer. It used to be the case that all pointers were nulled in debug & I recall something about turning this behaviour off, but I can't remember the full details right now.
Are the strings overrunning their variables? Unlikely with std::string, but worth eliminating.
几种可能性:
我猜你正在读取/写入超过本地数组末尾。 在调试版本中这可能有效,因为内存分配不紧密。 在发布版本中,这更有可能导致问题,具体取决于数组旁边分配的内容。
另一种可能性是您在某处有一个未初始化的指针。 VC默认在调试模式下初始化局部变量,但在发布模式下不初始化。 因此,代码如下:
通常在发布模式下失败。
Couple of possibilities:
I would guess that you are reading/writing past local array end. In debug builds this may work, as memory is not tightly allocated. In release builds this is more likely to cause problems, depends on what is allocated right next to the array.
Another possibility is that you have an uninitialized pointer somewhere. VC default initializes local variables in debug mode, but not in release mode. Thus code like:
Typically fails on release mode.
该错误消息强烈表明您存在内存问题,可能会覆盖内存。 这些很难找到,但您可以通过谷歌搜索“Visual C++内存损坏工具”找到一些可能的解决方案。
内存损坏的问题在于它是不可预测的。 它不一定会产生任何后果,即使发生也可能不会导致崩溃。 像这样崩溃是好的,因为它告诉你你遇到了问题。
摆弄调试与发布、添加或删除部分代码、更改优化选项等不太可能解决问题。 即使确实如此,如果进行任何更改,它也可能会突然出现。
所以,你遇到了内存损坏问题。 这些几乎总是很难找到,但有工具。 你需要解决这个问题。
您还可以看看您的商店做法。 您是否使用不太安全的构造(例如,
new
数组而不是vector>>
)? 您是否有编码标准来尝试降低风险? 你们有代码审查吗? 内存损坏可能是阴险且具有破坏性的,您希望尽可能避免它。The error message is strongly suggesting you have a memory issue, probably overwriting memory. These are hard to find, but you can find some possible solutions googling "visual c++ memory corruption tool".
The thing about memory corruption is that it's unpredictable. It doesn't necessarily have any consequences, and if it does they may not result in a crash. Crashing like that is good, because it informs you you've got a problem.
Fiddling with debug vs. release, adding or removing parts of code, changing optimization options and the like is unlikely to solve the problem. Even if it does, it's likely to crop up if any changes are made.
So, you've got a memory corruption problem. Those are almost always difficult to find, but there are tools. You need to fix that problem.
You might also look at your shop practices. Do you use less safe constructs (
new
arrays rather thanvector<>
, say)? Do you have coding standards to try to reduce risk? Do you have code reviews? Memory corruption can be insidious and damaging, and you want to avoid it as much as possible.您得到的是操作系统的系统异常。 这些不会被处理,因为它们不是 C++ 异常。 但是,您可以将其转换为 C++ 异常并像普通异常一样捕获它们。
这里有一篇很棒的文章 http://www .thunderguy.com/semicolon/2002/08/15/visual-c-exception-handling/(第 3 页),展示如何创建一个 Windows 异常类,该类将使用
_set_se_translator< 捕获异常/code> 方法并抛出 C++ 异常。 最棒的是您可以从 EXCEPTION_RECORD 结构中获取堆栈,尽管您必须添加该功能来处理该结构,但这将有助于缩小对该访问冲突的搜索范围。
What your getting is a system exception from the OS. These are not handled because they are not C++ exception. However you can convert then into a C++ exception and catch them like a normal exception.
There is a great article here http://www.thunderguy.com/semicolon/2002/08/15/visual-c-exception-handling/ (page 3) that shows how to create a Windows Exception class that will catch the exception using the
_set_se_translator
method and throw a C++ exception. The great thing is you can get a stack from the EXCEPTION_RECORD structure, although your'll have to add that functionality to process the structure, but it will help narrow your search for that access violation.我认为这里的问题是未初始化的局部变量。
在调试模式下,通常变量会被初始化,并且不会出现任何异常。
但在发布模式下可能会因此出现错误。
尝试查找未初始化的变量,其访问可能会导致异常。
假设您有布尔局部变量。
在调试版本中,bRet 将被初始化为 0,并且您的代码可以正常工作。
但在发布中它不会是 0 ,它将是一些随机值,并且您的代码可能会基于 bRet 执行某些操作。稍后可能会导致异常,因为 bRet 值是错误的。
I think the issue here is uninitialized local variable.
In Debug mode generally the variables get initialized and you don't get any exceptions.
But errors may occur in release mode because of this.
Try to look for uninitialized variable whose access may cause exception.
Suppose you have boolean local variable.
In debug build bRet will get initailized to 0 and your code just works fine .
But in release it won't be 0 , it would be some random value and your code might be doing something based on bRet .It may later cause an exception because bRet value is wrong.