c ++:本地数组定义与malloc调用
这有什么区别:
somefunction() { ... char *output; output = (char *) malloc((len * 2) + 1); ... }
还有这个:
somefunction() { ... char output[(len * 2) + 1]; ... }
什么时候比另一个更合适?
谢谢大家的回答。 这是一个总结:
- 恩。 1是堆分配
- 恩。 2是堆栈分配
- 堆栈有一个大小限制,用于较小的分配
- 你必须释放堆分配,否则它会泄漏
- 一旦函数退出,就无法访问堆栈分配
- 在您释放堆分配(或应用程序结束)之前,可以访问堆分配
- VLA不是标准C ++的一部分
更正欢迎。
这里有一些关于堆与堆栈之间差异的解释:
堆栈和堆的内容和位置是什么?
当您只有少量数据时使用本地数据,并且您不会使用您声明它所在函数范围之外的数据。如果您要传递数据,请使用malloc。
局部变量保存在堆栈上,其大小比堆大得多,其中使用malloc分配的数组。 我通常会在堆上放置> 16个字节的任何内容,但是你有更多的灵活性。 只是不要在kb / mb大小范围内分配本地 – 它们属于堆。
第一个在堆上分配内存。 你必须记住释放内存,否则它会泄漏。 如果内存需要在函数外部使用,或者需要分配大量内存,这是合适的。
第二个在堆栈上分配内存。 当函数返回时,它将自动回收。 如果您不需要将内存返回给调用者,这是最方便的。
第一个示例从堆中分配一个存储块。 第二个从堆栈中分配存储。 从somefunction()返回输出时,差异变得可见。 动态分配的存储仍然可供您使用,但第二个示例中基于堆栈的存储是,嗯,无处可去。 你仍然可以写入这个存储并读取它一段时间,直到你下次调用一个函数,此时存储将被随机覆盖返回地址,参数等。
这个问题中的代码还有很多其他奇怪的东西。 首先,这是一个c ++程序,你想要使用new而不是malloc(),所以你会说
output = new char[len+1];
而len * 2 + 1又是什么? 也许这是你的代码中的特殊内容,但我猜你要分配unicode字符或多字节字符。 如果它是unicode,则null终止需要两个字节以及每个字符,并且char是错误的类型,在大多数编译器中是8位字节。 如果它是多字节的,那么嘿,所有的赌注都关闭了。
首先是一些术语:
- 第一个样本称为堆分配 。
- 第二个样本称为堆栈分配 。
一般规则是:在堆栈上分配,除非:
- 编译时所需的数组大小未知。
- 所需的大小超过总堆栈大小的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’。