C 数组实例化 - 堆栈或堆分配?

Posted

技术标签:

【中文标题】C 数组实例化 - 堆栈或堆分配?【英文标题】:C Array Instantiation - Stack or Heap Allocation? 【发布时间】:2012-10-04 04:28:08 【问题描述】:

我保证以前有人问过这个问题,但我无法通过搜索找到它;提前对任何裁员表示歉意。

我的(可能是错误的)理解是,只有在编译时知道对象的大小时才分配给堆栈。因此,在初始化数组的情况下,您可以执行以下操作之一(这应该在堆栈上):

char charArray[50];

由于这个数组的大小在编译时是已知的,这应该没有问题。

另一方面,这(我相信)也是有效的代码:

char anotherCharArray[someVariable + 50];

这也会进入堆栈吗?如果你 free() this,我很确定代码会出现段错误,所以它让我认为它确实如此,但它对我来说真的没有意义。同样,当通过 malloc 分配数据时,您必须使用 free() 的 100% 唯一情况吗?

提前感谢您的帮助。

【问题讨论】:

@Shookit:你需要指明你是在谈论局部变量还是全局变量。 @PaulR 如果数组是可变长度的,则它不能在全局范围内。 您必须区分自动存储堆栈,后者是存储数据的低级方式。放置在自动存储中的数据也可以放置在其他地方,例如寄存器中。对于大小未知的本地数组(称为 VLA:s),编译器可以将其放在堆栈上,也允许在堆上分配内存(只要它在适当的位置释放它)。事实上,VLA:s 不能很好地与 setjmp/longjmp 一起使用,因为它们可能会泄漏(C 标准允许这样做)。 【参考方案1】:

如果char charArray[50]; 是在文件范围内定义的(在所有函数之外)或者是static,它不会在堆栈上,它将是在程序的开始变量处预分配的全局变量。如果它不是static 并且在函数范围内定义,它将在堆栈上。

char anotherCharArray[someVariable + 50]; 只能在函数范围内定义,并且将在堆栈上。

以上所有内容都适用于 C 的典型实现。非典型实现可能使用堆而不是堆栈,而不是程序数据部分中的预分配空间。

free() 没有分配给malloc()calloc()realloc()。简单的。某些功能可能意味着使用上述之一,例如POSIX strdup().

【讨论】:

如果我们在全局范围内,char someArray[variableLenght]; 是不允许的... @H2CO3 最近的编辑是否消除了歧义?我看不出我在哪里暗示在全球范围内这是允许的。【参考方案2】:

同样,当通过 malloc 分配数据时,您必须使用 free() 的 100% 唯一情况吗?

是的。 (除了 calloc 和 realloc,它们的返回值也是 free()'d。类似地,有些函数使用 malloc() 并且记录了这一事实,例如 strdup() - 这些函数的返回值也是显然要使用free() 释放。)

char anotherCharArray[someVariable + 50];

这也会进入堆栈吗?

是的,确实如此(在大多数实现中 - 当然,您认为并不总是正确,但在大多数平台上,确实如此)。是的,这是有效的代码,但它只是 C99 中的标准。

【讨论】:

好吧,看来我最大的误解是假设堆栈内存分配需要在编译时知道大小?我将此标记为已回答(但仍然可以随时回答我的评论:) @Shookit 是的,这完全是误解;具有已知大小与分配某物的位置无关。唯一的联系是,在以前的 C 版本中,由于各种历史原因,auto 变量必须具有已知大小,并且只能在堆栈上分配 auto 变量。 @JimBalter 很好地回答了你的问题 :) 太棒了,非常感谢大家的帮助。对我来说,必须在编译时知道它从来没有意义,因为您希望堆栈帧能够在内存空间内尽可能多地增长(直到调用另一个函数和一个新的堆栈帧已创建)。 即使您在编译时知道大小,如果超过几兆字节并且在堆栈上,在运行时某些 C 实现也会导致堆栈溢出。 ***.com/questions/27481707/…(哈。我第一次使用该网站自己的名称。)

以上是关于C 数组实例化 - 堆栈或堆分配?的主要内容,如果未能解决你的问题,请参考以下文章

如何实例化 int 类型的 Stacks 数组?

堆和堆栈内存是如何管理、实现和分配的?

使用 malloc() 分配的指针实例化一个类 [重复]

c++实例化一个对象

什么是更有效的堆栈内存或堆? [复制]

C函数中如何调用未实例化类的成员函数