使用堆栈以避免动态分配是不好的方式吗?

问题描述:

我明白这个非常类似的问题给出了答案: When is it best to use the stack instead of the heap and vice versa?使用堆栈以避免动态分配是不好的方式吗?

但我想确认:

这是一个非常简单的程序:

void update_p(double * p, int size){ 
    //do something to the values refered to by p 
} 

void test_alloc(int size){ 
    double p[size]; 
    unsigned int i; 
    for(i=0;i<size;i++)p[i]=(double)i; 
    update(&p,size); 
    for(i=0;i<size;i++)printf("%f\n",p[i]); 
} 

int main(){ 
    test_alloc(5); 
    return 1; 
} 

和test_alloc的替代版本:

void test_alloc(int size){ 
    double * p = calloc(sizeof(double),size); 
    unsigned int i; 
    for(i=0;i<size;i++)p[i]=(double)i; 
    update(p,size); 
    for(i=0;i<size;i++)printf("%f\n",p[i]); 
    free(p); 
} 

这似乎是两个版本都有效(?)。一个使用堆栈,另一个使用堆(?)。 两种方法都有效吗?他们的优点或问题是什么?

如果确实数组一旦从test_alloc退出就不会被使用,那么第一种方法更适合不需要内存管理(即忘记释放内存)吗?

如果test_alloc被大量调用,在堆中保留内存会花费更多时间,并且这会对性能产生影响吗?

会有什么理由使用第二种方法吗?

+0

当需要传递数据时,请使用堆,否则堆栈,就像链接中的帖子回复一样。在你的例子中,不需要使用堆,但是当程序变得更大时,你将需要将数据存储在堆中,因为它可以在任何地方传播。 – moeCake

+0

你自己给出了答案。 – user3007735

+0

是这样做的,但是让我怀疑的是一个警告:“从不兼容的指针类型更新参数1”。其实,应该在帖子中写下。 – Vince

在栈上分配的问题(或)堆是依赖于以下参数:

  • 要在其中变量可用范围和续航时间:说,在你的计划,如果你需要使用main中的test_alloc之后的double数组成员,你应该去动态分配。

  • 您的堆栈的大小:假设你正在使用的test_alloc功能,其中有4K堆栈线程的上下文,您的数组大小这又依赖于size变量账户1K,那么堆栈分配是不可取的,你应该去动态分配。

  • 复杂的代码:当使用动态分配,enusre照顾避免内存泄漏,悬摆指针等的这增加了复杂性的一些量的代码和更容易错误。

  • 分配的频率:在一个循环中调用mallocfree可以具有较小的性能。这一点是基于这样一个事实,即堆栈分配仅仅是取消SP的事情,相反,堆中的分配需要更多的记录。

+0

感谢您的答案。但是,你是否会对“从不兼容的指针类型更新参数1”发出警告进行解释? – Vince

+0

因为'p'是一个双精度数组,所以调用update函数作为'update(p,size)'。这是因为当你通过名称引用数组时,它会衰减到数组中第一个元素的指针,在这种情况下它将是一个'double *'。 –

在堆栈版本中,您不能分配具有100000000个元素的数组。当使用堆栈分配小数组时,速度更快。当分配非常大的数组时,使用堆。

约栈,堆内存分配

的更多信息,请考虑以下文字: Stack-based memory allocationHeap-based memory allocation

“如果test_alloc被大量调用,是它更耗时堆中保留内存,可能这有任何影响性能?”

嗯,我想你正在从堆栈和堆分配性能。总是堆栈分配速度更快,因为它只是移动堆栈指针。堆分配肯定需要更多时间,因为它必须执行内存管理。所以如果你在上述函数中没有太多的操作不会导致堆栈溢出(因为在堆栈上创建太多的对象会增加堆栈溢出的机会),并且你不需要这个变量的作用域就可以可能使用堆栈本身。

所以要回答你的问题,如果你没有在堆栈上使用太多的对象并导致堆栈溢出,那么使用堆栈来避免动态分配并不坏。

希望这会有所帮助。