c ++:本地数组定义与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. VLA不是标准C ++的一部分

更正欢迎。

这里有一些关于堆与堆栈之间差异的解释:
堆栈和堆的内容和位置是什么?

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

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

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

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

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

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

 output = new char[len+1]; 

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

首先是一些术语:

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

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

  1. 编译时所需的数组大小未知。
  2. 所需的大小超过总堆栈大小的10%。 Windows和Linux上的默认堆栈大小通常为1或2 MB。 因此,本地arrays不应超过100,000个字节。

您使用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’。