c ++:本地数组定义与malloc调用

时间:2010-07-17 00:16:04

标签: c++ c arrays malloc

这有什么区别:

somefunction() {  
    ...  
    char *output;   
    output = (char *) malloc((len * 2) + 1);  
    ...  
}  

和此:

somefunction() {  
    ...  
    char output[(len * 2) + 1];  
    ...  
}  

什么时候比另一个更合适?

感谢所有人的回答。这是一个总结:

  1. 离。 1是堆分配
  2. 离。 2是堆栈分配
  3. 堆栈有一个大小限制,用于较小的分配
  4. 你必须释放堆分配,否则它会泄漏
  5. 一旦函数退出
  6. ,就无法访​​问堆栈分配
  7. 可以访问堆分配,直到您释放它(或应用程序结束)
  8. VLA不是标准C ++的一部分
  9. 更正欢迎。

    这里有一些关于堆与堆栈之间差异的解释:
    What and where are the stack and heap?

5 个答案:

答案 0 :(得分:6)

第一个在堆上分配内存。你必须记住释放内存,否则它会泄漏。如果需要在函数外部使用内存,或者需要分配大量内存,这是合适的。

第二个在堆栈上分配内存。当函数返回时,它将自动回收。如果您不需要将内存返回给调用者,这是最方便的。

答案 1 :(得分:5)

当您只有少量数据时使用本地数据,并且您不会使用您声明的函数范围之外的数据。如果您要传递数据,请使用malloc

局部变量保存在堆栈上,其大小比堆大得多,其中使用malloc分配的数组。我通常会去寻找任何东西> 16个字节放在堆上,但你有更多的灵活性。只是不要在kb / mb大小范围内分配本地 - 它们属于堆。

答案 2 :(得分:5)

第一个示例从堆中分配一个存储块。第二个从堆栈中分配存储。从somefunction()返回输出时,差异变得可见。动态分配的存储仍然可供您使用,但第二个示例中基于堆栈的存储是,嗯,无处可去。您仍然可以写入此存储并暂时读取它,直到下次调用函数为止,此时存储将被随机返回,返回地址,参数等。

在这个问题中,代码中还有很多其他奇怪的东西。首先,这是一个c ++程序,你想使用new而不是malloc(),所以你要说

output = new char[len+1];

而len * 2 + 1又是什么?也许这是你的代码中的特殊内容,但我猜你要分配unicode字符或多字节字符。如果它是unicode,则null终止需要两个字节以及每个字符,并且char是错误的类型,在大多数编译器中是8位字节。如果它是多字节的,那么嘿,所有的赌注都已关闭。

答案 3 :(得分:3)

首先是一些术语:

  • 第一个样本称为堆分配
  • 第二个样本称为堆栈分配

一般规则是:在堆栈上分配,除非:

  1. 在编译时,所需的数组大小是未知的。
  2. 所需尺寸超过总堆叠尺寸的10%。 Windows和Linux上的默认堆栈大小通常为1或2 MB。所以你的本地数组不应超过100,000字节。

答案 4 :(得分:1)

您使用C ++和C标记了您的问题,但C ++中不允许使用第二个解决方案。可变长度数组仅允许在C(99)中使用。

如果你假设'len'是常数,那么两者都可以。

malloc()(和C ++的'new')在堆上分配内存,这意味着你必须free()(或者如果你用'new','delete'分配)缓冲区,或者内存永远不会被收回(泄漏)。

后者在堆栈上分配数组,当它超出范围时将会消失。这意味着您不能将指针返回到分配范围之外的缓冲区。

当您想要传递内存块时,前者非常有用(但在C ++中,最好使用RAII类进行管理,而不是手动),而后者最适合只需要的小型固定大小数组存在于一个范围内。

最后,您可以使用'static'标记堆叠分配的数组,以将其从堆栈中取出并进入全局数据部分:

static char output[(len * 2) + 1];

这使您能够返回指向其作用域之外的缓冲区的指针,但是,对此类函数的所有调用都将引用相同的全局数据,因此如果每个需要一个唯一的内存块,请不要使用它时间。

最后,除非你有充分的理由(即realloc),否则不要在C ++中使用malloc。改为使用'new',随附'delete'。