具有自动存储持续时间未定义行为的"太大"对象?

Ste*_*ner 11 c language-lawyer

关于SO 的最近一个问题 "为什么在这种特定情况下在堆栈上分配大元素不会失败?" 以及关于"堆栈上的大型阵列"或"堆栈大小限制"的一系列其他问题让我搜索标准中记录的相关限制.

我知道C标准没有指定"堆栈",因此它没有为这样的堆栈定义任何限制.但我不知道了,其SIZE_Xvoid foo() { char anArray[SIZE_X]; ... }标准保证了程序的工作,并发生了什么事,如果程序超出此SIZE_X.

我发现了以下定义,但我不确定这个定义是否实际上是对具有自动存储持续时间的特定支持对象大小的保证(参见在线C11标准草案):

5.2.4.1翻译限制

(1)实现应能够翻译和执行至少一个包含以下每个限制的至少一个实例的程序:

...

对象中的65535个字节(仅限托管环境中)

这是否意味着实现必须支持一个价值高达65535SIZE_X像一个功能void foo() { char anArray[SIZE_X]; ... },并且大于任何价值65535SIZE_X是未定义的行为?

对于堆,调用malloc返回NULL让我控制请求"太大的对象"的尝试.但是,如果程序"请求具有自动存储持续时间的过大对象",我该如何控制程序的行为,特别是如果没有记录这样的最大大小,例如在某些情况下limits.h?那么有可能编写一个便携式功能,如checkLimits()支持"入口屏障",如:

int main() {
   if(! checkLimits()) {
      printf("program execution for sure not supported in this environment.");     
      return 1;
   } else {
      printf("might work. wish you good luck!"); 
   }
   ...
}
Run Code Online (Sandbox Code Playgroud)

Eri*_*hil 5

从技术上讲,实现只需要翻译并执行一个带有65,535字节对象(以及列出的其他内容)的程序,以符合标准.它可能会失败所有其他人.

要了解更大的程序是否有效,您必须依赖于特定实现的详细信息.大多数实现提供的堆栈空间多于64 KiB,尽管它可能没有文档记录.可能存在用于调整允许的堆栈空间的链接器开关.

例如,对于ld当前macOS上的链接器,默认值为8 MiB,并且该-stack_size开关可用于设置更多或更少(对于主线程).

我想说,因为C标准说堆栈空间等环境限制可能会限制实现,除了一个特定的示例程序必须工作的事实之外的任何事情都是技术上未定义的行为.

  • "大多数实现提供的堆栈空间超过64 KiB" - >每年有数百万的嵌入式处理器使用C,具有不同程度的有限资源,所以我对"最"有疑问. (2认同)
  • @chux:如果你想要技术性的,我希望这些都不是 C 实现,因为它们都没有记录 C 标准需要实现来记录的所有内容。我相信符合 C 实现的数量为零,其中 51% 拥有大型堆栈。 (2认同)
  • 当然同意0部分的51%. (2认同)