【问题标题】:Can an access violation be a disguised out-of-memory error?访问冲突可以是伪装的内存不足错误吗?
【发布时间】:2019-01-16 09:27:42
【问题描述】:

我正在调试 64 位 C++(托管)故障转储(访问冲突)。

转储的总大小为 32.374.535 kb。

应用程序是多线程的,对应的调用栈只提到mscvrt.dll!memcpy(不知道是哪个线程在创建这个)。显然没有对应的源码。

Visual Studio Locals 窗口为空。

未处理的异常提到Access violation writing location 0x000000F02A6BB000,但在那个位置,似乎什么都没有:

0x000000F02A6BAF84  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ..............................................................
0x000000F02A6BAFC2  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ..............................................................
0x000000F02A6BB000  ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??  .............................................................. <= here it is.
0x000000F02A6BB03E  ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??  ..............................................................

我看不出为什么在这个内存位置上写入会导致任何问题,因此我相信(基于转储的大小)我正在处理内存错误(这意味着无法复制一些东西进入内存,因为已经使用了太多内存,没有空间了)。但是,如果这是真的,那内存位置不应该有一些信息吗?

有人知道吗?

【问题讨论】:

  • 写入(甚至读取)您不“拥有”的内存会导致未定义的行为。如果没有来源,真的很难找到问题以及导致问题的原因。无论如何,也几乎不可能修复它。至于猜测可能的原因,可能是使用了未初始化的局部指针变量?
  • 所有?? 让我觉得这个地址的内存不属于被调试的进程。 (即使调试器也不愿意或无法读取它。)所以,这看起来真的像“访问冲突”。
  • @Scheff:“不属于被调试的进程”是什么意思?我认为,在 Windows 中,每个进程都有权不受限制地使用每一块空闲内存来完成其工作(当然,除非计算机内存不足)。你能确认一下吗?我在哪里可以找到相关信息?
  • 内存可以写保护。此外,如果调用堆栈上唯一的东西是 memcpy,那么您可能已经严重破坏了堆栈。
  • 绝对不是。每个进程都必须从操作系统(Windows 内核)请求内存块。之后它可以独占地读/写访问这个内存。整体内存的其他部分必须是不可访问的。这是为了保护进程免受彼此的影响。 Wikipedia: Memory Protection

标签: c++ memory-management access-violation memcpy crash-dumps


【解决方案1】:

没有看到源代码,就无法知道如果遇到内存不足错误会发生什么。肯定有很多程序不会检查每个内存分配是否失败,因此它们的代码可能会完全脱轨。

未检查的内存不足错误的最常见结果是访问冲突,但它通常位于一个非常小的地址或其中包含一些明显的无意义模式。这是因为许多内存分配函数在内存不足时返回零,并且检查失败可能导致访问返回值附近的地址。此外,某些函数未初始化结果并返回单独的错误。未能检查该错误可能会导致使用未初始化的值来访问内存,这通常看起来很奇怪。

在这里,地址看起来很合理。但谁知道呢。也许代码分配了一个新缓冲区,释放旧缓冲区,并将旧地址切换为新缓冲区,但是在出错时,不切换地址而是释放旧地址,导致释放后访问。没有源代码就无从得知。

【讨论】:

    【解决方案2】:

    直观地说,在我看来,它不像是内存不足错误。一些设计不佳的操作系统上的内存分配系统服务在分配内存失败时会返回成功值。像Windoze一样有很多缺陷,我不相信它是这样一个系统。如果您在确实会进行某种延迟分配的系统上运行,那么我会怀疑您的怀疑。

    我认为,您遇到了内存溢出,导致写入尚未映射到地址空间的页面。

    【讨论】:

      【解决方案3】:

      确实有可能访问冲突实际上是内存不足错误(或其他类型的内存相关错误),如 Scheff 和 Peter 的 cmets 中所述。

      在这种特殊情况下,转储的大尺寸 (±33Gb) 表明应用程序(连同其他应用程序)可能会消耗过多的内存。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-04-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-05-22
        • 2017-11-05
        相关资源
        最近更新 更多