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 数组实例化 - 堆栈或堆分配?的主要内容,如果未能解决你的问题,请参考以下文章