在堆栈上增长数组

Growing an array on the stack

这本质上是我的问题。在一个函数的生命周期中,我生成一些整数,然后在一个算法中使用整数数组,该算法也是同一函数的一部分。整数数组只会在函数内使用,所以将数组存储在堆栈上自然是有意义的。

问题是在生成所有整数之前我不知道数组的大小。

我知道如何在堆栈上分配固定大小和可变大小的数组。但是,我不知道如何在堆栈上增加数组,这似乎是解决我的问题的最佳方法。我相当确定这在汇编中是可能的,您只需增加堆栈指针并为每个生成的 int 存储一个 int,因此 int 数组将位于堆栈帧的末尾。这在 C 中可以做到吗?

我不同意你的断言"so naturally it makes sense to store the array on the stack"。堆栈内存实际上是为您在编译时知道大小时而设计的。我认为动态内存是解决问题的方法

为了解决您的问题,动态内存分配看起来很理想。

int *a = malloc(sizeof(int));

并取消引用它以存储值。 每次需要将一个新整数添加到现有整数列表中时

int *temp = realloc(a,sizeof(int) * (n+1)); /* n = number of new elements */
if(temp != NULL)
a = temp;

使用此内存后free()它。

不要在堆栈上使用动态数组(比较Why is the use of alloca() not considered good practice?),最好使用malloc从堆中分配内存并使用realloc调整大小。

C 编译器的内部结构要求堆栈大小在编译时是固定的或可计算的。自从我使用 C(现在是 C++ 转换)以来已经有一段时间了,我不知道这是为什么。 http://gribblelab.org/CBootcamp/7_Memory_Stack_vs_Heap.html 对两种方法的优缺点进行了有用的比较。

我很欣赏你的汇编代码类比,但 C 在很大程度上是由操作系统管理的,如果这有意义的话,imposes/provides 任务、进程和堆栈符号。

C 没有定义 "stack" 是什么。它只有静态、自动和动态分配。静态和自动分配由编译器处理,只有动态分配才能将控制权交到您手中。因此,如果你想手动释放一个对象并分配一个更大的对象,你必须使用动态分配。

永远不要使用 alloca()

恕我直言,这一点在标准参考文献中做得不够好。

一个经验法则是:

If you're not prepared to statically allocate the maximum possible size as a fixed length C array then you shouldn't do it dynamically with alloca() either.

为什么?您试图避免 malloc() 的原因是性能。

alloca() 会更慢并且在任何情况下都不起作用静态分配将失败。它通常也比 malloc() 更不可能成功。

有一点是肯定的。静态分配最大值将超过 malloc()alloca()。 静态分配通常在空操作附近该死。大多数系统无论如何都会为函数调用推进堆栈指针。距离有多远没有明显差异。

所以你告诉我的是你关心性能但想阻止空操作解决方案?想想你为什么会有这种感觉。

极有可能是您担心分配的大小。

但如前所述,它是免费的,但会被收回。有什么好担心的? 如果担心 "I don't have a maximum or don't know if it will overflow the stack" 那么你不应该使用 alloca() 因为你没有最大值并且知道它是否会溢出堆栈。

如果您确实有最大值并且知道它不会破坏堆栈,那么静态分配最大值并回家。免费午餐 - 记得吗?

这使得 alloca() 要么是错误的,要么是次优的。

每次您使用 alloca() 时,您要么是在浪费时间,要么是在一种难以测试的任意缩放上限中进行编码,该上限会安静地休眠,直到事情真正重要,然后 f**k up某人的一天。

不要。

PS: 如果你需要一个大的 'workspace' 但 malloc()/free() 开销是一个瓶颈例如在一个大循环中重复调用,然后考虑在循环外分配工作空间并将其从一个迭代带到另一个迭代。如果发现 'big' 情况,您可能需要重新分配工作区,但通常可以将分配数除以 100 甚至 1000。

脚注: 必须有一些理论算法,其中 a() 调用 b() 并且如果 a() 需要大量环境 b() 则不需要,反之亦然。 在这种情况下,可能会出现某种奇怪的附加赛,其中堆栈溢出被 alloca() 阻止了。我从未听说过或见过这样的算法。收到合理的标本将不胜感激!