【问题标题】:What are the parameters of the 0xC00000FD (Stack Overflow) error?0xC00000FD(堆栈溢出)错误的参数是什么?
【发布时间】:2021-11-22 10:45:03
【问题描述】:

我创建了一个函数,它在堆栈 (C++) 上分配一个太大的数组。运行结果出现此错误:

Unhandled exception at 0x000000013F4DEBF7 in xxx.exe: 0xC00000FD: Stack overflow (parameters: 0x0000000000000001, 0x0000000000043000).

我从未见过分配给堆栈溢出错误的特定实例的“参数”部分,而且我在 Internet 上的搜索没有结果。有谁知道这些参数是什么意思?我观察到,对于相同代码的多次运行,第一个参数保持不变,第二个参数发生变化,但保持在 6-5 位范围内。我很好奇他们的意思。

如果重要,这里有一个 MRE:

constexpr uint8_t LOG_2_OF_BUCKET_COUNT = 20;

int main(){
    uint32_t histogram[1 << LOG_2_OF_BUCKET_COUNT];
    return 0;
}

【问题讨论】:

  • @Nate:这是一个操作系统“结构化异常”,结构化异常详细信息不依赖于工具链(构建或运行时)。只是操作系统。
  • 您的数组大约 4MB,对于堆栈来说可能太大了。试试std::vector&lt;uint32_t&gt; histogram(1 &lt;&lt; LOG_2_OF_BUCKET_COUNT);
  • @churill 别担心,问题不在于我应该如何修复我的代码。只是参数,我会处理其余的。不过感谢您的努力。

标签: c++ windows visual-c++ runtime-error stack-overflow


【解决方案1】:

the documentation for the EXCEPTION_RECORD structure 中描述了“参数”。该异常消息中的所有内容都来自EXCEPTION_RECORD,首先是ExceptionAddress,然后是从ExceptionAddress 派生的模块名称,然后是ExceptionCode 及其友好名称,最后是NumberParametersExceptionInformation[] 读取。

不幸的是,出于您的目的,官方文档仅描述了 EXCEPTION_ACCESS_VIOLATIONEXCEPTION_IN_PAGE_ERROR 的参数,并说对于所有其他异常类型,参数数组具有未定义的内容。

注意这一点,记录它们的两种异常类型的参数之间存在一致性,并且堆栈溢出是通过访问冲突在内部检测到的,因此按照EXCEPTION_ACCESS_VIOLATION 的描述进行解码是有意义的。具体来说:

  • 数组的第一个元素包含一个读写标志,指示导致访问冲突的操作类型。

    • 如果此值为零,则线程试图读取不可访问的数据。
    • 如果此值为 1,则线程尝试写入不可访问的地址。
    • 如果此值为 8,则线程会导致用户模式数据执行保护 (DEP) 违规。
  • 第二个数组元素指定不可访问数据的虚拟地址。

与您捕获的异常信息相比,第一个元素是(非法读取/非法写入/NX 违规)标志是完全可信的。然而,第二个元素看起来不太像虚拟地址。也许对于EXCEPTION_STACK_OVERFLOW,它是相对于线程堆栈基地址报告的。

【讨论】:

  • "通过访问冲突在内部检测到堆栈溢出" - 嗯?你从哪里得到的?
  • @RemyLebeau:快速概览堆栈增长的工作原理:堆栈末尾有一个保护页,没有读取、写入和执行访问权限。当它被触及时,CPU 会产生访问冲突错误,并且操作系统错误处理程序要么将更多页面提交到保留的堆栈地址空间并设置新的保护页面,要么在提交完整的保留空间时引发堆栈溢出异常。 (访问冲突错误的操作系统处理程序也可能导致分页,管理写时复制,或引发不在堆栈保护页面上的 AV 错误的访问冲突异常)
  • @RemyLebeau:这种保护页面机制就是为什么大多数人为EXCEPTION_ACCESS_VIOLATION 编写用户模式处理程序可以很好地捕捉到第一次出现但通常会看到他们的程序在第二次发生堆栈溢出时立即崩溃线程——因为编译器提供了所有的堆栈展开逻辑,但没有人在展开后重新创建保护页。
  • @BenVoigt 我知道堆栈增长的工作原理。它不使用EXCEPTION_ACCESS_VIOLATION 处理,而是使用STATUS_GUARD_PAGE_VIOLATION。两种不同的东西。
  • @RemyLebeau:我没有说它是EXCEPTION_ACCESS_VIOLATION 我说它是相同的访问冲突 CPU 陷阱/故障。在其他条件下,那个也产生EXCEPTION_ACCESS_VIOLATION。它来自同一个内核提供的故障处理程序,因此可以合理地认为故障处理程序可能以相同的方式为两个异常设置参数。当然,我们进入的领域是 CPU 陷阱/故障的正式名称可能因 Windows 支持的不同架构(ix86、amd64、Itanium、Alpha、ARM)而异
猜你喜欢
  • 1970-01-01
  • 2010-11-09
  • 2011-04-23
  • 1970-01-01
  • 2010-09-11
  • 2011-10-22
  • 1970-01-01
  • 2012-05-10
  • 2019-01-09
相关资源
最近更新 更多