“0xc0000005”访问冲突的范围是什么?(这是一个关于IT技术的提问标题)

39
我想了解一下0xc0000005异常具体涵盖什么内容。
也就是说,如果一个应用程序试图访问已释放的内存或属于另一个进程的内存,是否会出现此异常。
但是对于例如映射到硬件的地址呢?或者超出有效范围的地址呢?尝试访问这些地址是否会出现相同的错误代码还是有自己的代码?
这是否包括对进程拥有的有效地址的读取失败?
基本上,我想知道当应用程序出现此异常时,可能出现了什么问题;这是一个可能只来自应用程序代码的狭窄错误,还是可能包括硬件问题在内的各种问题?
(我知道肯定有MSDN页面介绍这个问题,但是搜索谷歌或MSDN会出现预期的100页随机应用程序故障排除;)
谢谢!
3个回答

42

你需要阅读处理器手册来深入了解这个问题。它由"陷阱"触发,最好描述为处理器中的异常。 陷阱中断代码执行并让操作系统的"catch"处理程序处理故障。一个非常普遍且无害的陷阱是页面故障,当处理器尝试从尚未映射的RAM中读取数据时引发它。 这就是虚拟内存的实现方式。

AccessViolation 属于一组操作系统不知道如何处理的硬错误陷阱。在处理器手册中称为"通用保护故障"。 它是一个抓住包,有很多方法可以触发GPF。迄今为止最常见的一个是尝试读取未映射的内存,通常是由堆内存损坏引起的。 其次是尝试执行无效或只能由特权代码执行的机器代码指令,通常是由栈内存破坏引起的。

这些陷阱是最难处理的,处理器无法继续执行程序。 操作系统肯定不知道如何处理它,因此会引发AccessViolation异常,以使程序有机会将处理器拉回已知的良好代码。 可以通过在代码中使用__try/__except关键字来实现。 不过这不是个好主意,除了用于自定义错误报告之外,你没有真正的办法知道程序状态在死亡之前是如何发生变异的,也无法恢复它。

如果没有此类SEH处理程序,则会进入Windows提供的后备处理程序。 你可以使用SetUnhandledExceptionFilter()提供自己的处理程序,有用于自定义崩溃报告。 系统提供的处理程序通过触发Windows错误报告组件WER来结束这一切。最终终止该进程。


1
非常感谢清晰而准确的解释。我之前并不知道这是来自处理器本身,这样想起来更合理。确实“坏得无法再坏了”!不禁让我想知道,在这些异常/陷阱/中断触发时,处理器何时开始反馈有用信息。 - sebf

23
首先,您需要了解用户模式进程中的地址是虚拟地址。它们不是用于访问硬件的实际地址。而是CPU中有一个虚拟到物理的转换电路(内存管理单元的一部分),它在“转换后备缓冲区”中查找匹配条目。在每次上下文切换期间,操作系统会使用属于您的进程的内存映射填充TLB。
因此,无法尝试访问其他进程的内存,也无法尝试访问硬件。这并不是因为这种访问被检测到并失败了,而是因为不存在用于未属于您的程序的内存的映射。
如果您的程序访问不映射到任何位置的地址,则会像Hans所说发生陷阱。这与“页面错误”和“访问违规”是同样的。首先,操作系统将检查地址是否有效但未在TLB中(例如,您的PC耗尽了内存,并将某些内存交换到磁盘)。在这种情况下,操作系统将把数据移到物理RAM中,在TLB中设置正确的映射,然后继续运行您的程序。如果操作系统确定地址完全无效(没有与其关联的交换位置),则会生成“访问违规”(Windows命名)或“段错误”(POSIX命名)。
通常的原因是逻辑错误,但如果您有例如RAM故障导致指针中的一个位发生更改,则硬件故障也可能触发访问违规。

感谢您对TLB工作原理的描述,这对于理解这些异常发生的方式非常有帮助。我发现所有这些技术细节都非常有趣,尽管我现在感到非常愚蠢,因为我一直以来对架构的用户模型只是一个更大版本的简单处理器,而我习惯于使用它们。我会尝试找到x86手册,以便我能够正确理解它。 - sebf

-1
我在 Google 上第一次搜索“访问冲突”(不带引号)时得到了this。虽然我不确定具体情况,但是 AV 的意思是:处理器尝试从或写入当前状态不允许的特定地址。这可能是硬件问题、总线错误、未映射的虚拟内存、坏 CPU,以及几乎任何违反访问保护的情况。

1
通常是由软件故障引起的。 - Zeek2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接