C 标准是否定义了堆栈溢出行为?

发布于 2024-07-15 06:53:22 字数 80 浏览 3 评论 0原文

是否有处理堆栈溢出的定义行为?

除了终止进程之外,似乎没有什么可以做的。 我只是想知道是否有人知道 C 标准对此有何规定。

Is there a defined behavior for handling a stack overflow?

Apart from terminating the process, it doesn't seem like there's a whole lot that can be done. I'm just wondering if anyone might know what the C standard has to say about it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

往昔成烟 2024-07-22 06:53:22

该标准不要求使用堆栈,并且对堆栈溢出没有任何规定。

The standard does not require the use of a stack, and has nothing to say about stack overflows.

2024-07-22 06:53:22

C99 标准没有定义堆栈; 它仅抽象地讨论自动或分配存储,而具有溢出检测的连续堆栈只是实现自动存储的一种机制。

标准第 7.14 节将 SIGSEGV 定义为“对存储的无效访问”时发生的信号。 C 的实现不需要生成任何信号,但如果检测到堆栈溢出,使用连续固定大小堆栈*的实现通常会发出 SIGSEGV 信号。

您可以为 SIGSEGV 注册信号处理函数,但它不能返回 - "[i]f 并且当函数返回时,如果 sig 的值为 SIGFPE、SIGILL、SIGSEGV 或任何其他实现定义的值对应于计算异常,行为未定义”

(*并不是说我故意使用不这样做的 C 实现,但我不知道 C 标准中的任何内容阻止使用用于在其他环境中实现可增长的自动存储域的通用技术)

The C99 standard doesn't define a stack; it only discusses automatic or allocated storage in the abstract, whereas a contiguous stack with overflow detection is only one mechanism for implementing automatic storage.

Section 7.14 of the standard defines SIGSEGV as the signal which occurs on "an invalid access to storage". Implementations of C are not required to generate any signals, but implementations using a contiguous fixed size stack* typically signal SIGSEGV if a stack overflow is detected.

You can register a signal handler function for SIGSEGV, but it can't return - "[i]f and when the function returns, if the value of sig is SIGFPE, SIGILL, SIGSEGV, or any other implementation-defined value corresponding to a computational exception, the behavio[u]r is undefined".

(* not that I've knowingly worked with C implementations which don't, but I'm not aware of anything in the C standard preventing the use of common techniques used to implement growable automatic storage domains in other environments)

第七度阳光i 2024-07-22 06:53:22

C 标准甚至没有定义堆栈,因此它当然没有定义堆栈溢出时会发生什么。

The C standard doesn't even define a stack, so it certainly doesn't define what happens when the stack overflows.

冷月断魂刀 2024-07-22 06:53:22

这里的答案是正确的,表明它与 c 标准无关,但你的陈述“除了终止进程之外,似乎没有很多可以做的事情”不是 - 作为一般性 -真的。

事实上,在大多数具有虚拟内存管理和按需分页的系统上,分配的堆栈非常小(通常比当前使用的多 4KB)并且经常溢出(这会生成页面错误中断),操作系统只需添加另一页即可线程的内存到堆栈。

堆栈限制(通常为 1MB)只是一个相当随意的数字,用于防止程序失控,通常不是绝对限制(尽管它适用于某些采用英特尔处理器 IIRC 的内存型号)。 为每个线程分配 1MB 物理内存通常没有意义。

The answers here are correct in stating that it is nothing to do with the c standard but your statement that "Apart from terminating the process, it doesn't seem like there's a whole lot that can be done" is not - as a generality - true.

In fact, on most systems with virtual memory management and on demand paging, the allocated stack is quite small (typically 4KB more than is currently being used) and often overflows (which generates a page fault interrupt) and the OS simply adds another page of memory to the stack for the thread.

The stack limit of - typically - 1MB, is just a fairly arbitrary figure chosen to guard against runaway programs and generally isn't an absolute limit (though it was on some memory models with intel processors IIRC). It would generally not make sense to allocate 1MB of physical memory to each thread.

冷夜 2024-07-22 06:53:22

根据这个问题,C标准甚至没有任何关于堆栈存在的说法,更不用说堆栈溢出了。

According to some answers to this question, the C standards don't even have anything to say about the existence of a stack, let alone a stack overflow.

榕城若虚 2024-07-22 06:53:22

我相当确定所发生的事情的细节是由操作系统定义的,但是,在所有情况下,程序都应该退出。 您的假设是正确的,一旦发生堆栈溢出,您实际上无能为力(至少作为程序员)。 你真正能做的就是从一开始就阻止它们发生。

I'm fairly sure the specifics of what happen are defined by the operating system however, in all cases, the program should exit. You are correct in assuming that there is really nothing you can do once a stack overflow occurs (at least as a programmer). All you can really do is prevent them from happening in the first place.

此生挚爱伱 2024-07-22 06:53:22

这取决于操作系统。 不过,许多操作系统允许覆盖默认堆栈大小。 例如,在 Windows 上,您可以使用此链接器标志< /a> 将堆栈大小从 1MB 增加到更高的值。

It's up to the operating system. Many operating systems allow the default stack size to be overwritten, though. For example, on Windows, you can use this linker flag to increase the stack size from 1MB to a higher value.

篱下浅笙歌 2024-07-22 06:53:22

正如其他人提到的,该标准没有提及任何有关堆栈的内容。

但是,我认为它是为了定义堆栈溢出行为,标准会说它会导致未定义的行为。

::边缘射击::

As other people have mentioned, the standard does not say anything about a stack.

But, I think it it were to define stack overflow behavior, the standard would say it results in undefined behavior.

::rimshot::

浅忆流年 2024-07-22 06:53:22

C 标准在这方面是矛盾的。 考虑以下程序:

void foo(uintptr_t n)
{
    int a;
    printf("%p\n", (void *)&a);
    if (n+1) foo(n+1);
}
int main()
{
    int a;
    printf("%p\n", (void *)&a);
    foo(0);
}

该程序完全符合并且不违反任何最小翻译限制,并且正如其他人所说,标准语言中没有关于堆栈限制/溢出的内容。 但是,它会生成 UINTPTR_MAX+2 个对象 a(在每个调用级别),其生命周期全部重叠,每个对象都有不同的地址。 仅仅通过计数论证这是不可能的。

The C standard is contradictory in this regard. Consider the following program:

void foo(uintptr_t n)
{
    int a;
    printf("%p\n", (void *)&a);
    if (n+1) foo(n+1);
}
int main()
{
    int a;
    printf("%p\n", (void *)&a);
    foo(0);
}

This program is perfectly conforming and does not violate any of the minimum translation limits, and as others have said, there is nothing in the language of the standard about stack limits/overflow. However, it produces UINTPTR_MAX+2 objects a (at each call level), whose lifetimes all overlap, each with distinct addresses. This is impossible by a mere counting argument.

若能看破又如何 2024-07-22 06:53:22

在某些系统上,确保堆栈溢出后任何类型的可预测的支持都会给每个函数调用增加相当大的开销; 因此,该标准相当合理地将堆栈溢出视为未定义行为。 如果目标是最大化实现运行合法程序的效率,那么这是完全合适的。

该标准也不要求系统有足够的堆栈来支持任何重要的函数调用深度。 鉴于一些有用的程序(特别是在嵌入式系统领域)可以使用少于 16 字节的堆栈,并且可能不一定能够腾出更多的 RAM,因此需要大量堆栈将违反“不使用堆栈”的理念。不要为不需要的东西付费”。

不幸的是,事实上,程序无法说明它需要什么类型的深度,也无法查询可用的堆栈类型,唯一可以保证不参与未定义行为的程序是那些使用堆栈的程序低于最低保证; 在嵌入式系统世界之外,这基本上意味着该标准对任何大于玩具的程序不提供任何保证。

On some systems, ensuring any kind of predictable favor after a stack overflow would add considerable overhead to every function call; thus, the standard quite reasonably regards stack overflow as Undefined Behavior. This is entirely appropriate if the goal is to maximize the efficiency with which an implementation can run legitimate programs.

The standard also doesn't require that systems have enough stack to support any non-trivial depth of function calls. Given that some useful programs (especially in the embedded-systems world) can get by with less than 16 bytes of stack, and may not necessarily be able to spare any more RAM than that, requiring a generous stack would violate the philosophy of "don't pay for what you don't need".

Unfortunately, the fact that there's no way for a program to say anything about what sort of depth it will require, nor query what sort of stack is available, the only programs which can be guaranteed not to engage in Undefined Behavior are those whose stack usage is below the minimum guarantees; outside of the embedded systems world, that basically means that the standard guarantees nothing about any program which is larger than a toy.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文