通过malloc进行VLA和动态内存分配有什么区别?

我很好奇这个:

有什么不同之处:

const int MAX_BUF = 1000; char* Buffer = malloc(MAX_BUF); 

和:

 char Buffer[MAX_BUF]; 

 char* Buffer = malloc(MAX_BUF); 

创建一个char指针Buffer ,通过malloc动态分配MAX_BUF字节的内存,并使Buffer指向已分配空间的开头。 此内存在堆上分配。

 char Buffer[MAX_BUF]; 

创建一个大小为MAX_BUF的数组BufferMAX_BUF可容纳MAX_BUF字符。 请注意,您正在创建可变长度数组 ( C99中引入的function),因为MAX_BUF是一个变量。 可以在堆栈上创建此数组。

除了别人说的,我还会在内存管理方面添加一些信息。

1)主要区别在于:

 const int MAX_BUF = 1000; char* Buffer = malloc(MAX_BUF); 

您需要手动管理分配的内存,例如,在使用完毕后使用免费Buffer 。 忘记free它(或释放它两次)可能会导致麻烦。

2)第二种情况:

 char Buffer[MAX_BUF]; 

你不需要任何东西。 它会自动销毁。 因此,您可以避免处理内存的任务 – 这很好。 您应该尝试总是评估您需要的方法。

一些观点。

  • 由于第二个是在堆栈上分配的,因此在需要创建大型数组时也会采用第一种方法 – 因为堆上通常可以使用更多内存。
  • 此外,如果您在方法中使用第二种方法创建数组,则对象的生命周期将是该方法 – 您将无法在该方法之外使用该数组。 而动态分配并非如此。
  • 案例1:在

      char Buffer[MAX_BUF]; 

    Buffer是一个大小为MAX_BUF数组 。 分配技术称为VLA 。

  • 案例2:在

     const int MAX_BUF = 1000; char* Buffer = malloc(MAX_BUF); 

    Buffer是一个指针 ,它被分配一个大小为MAX_BUF的内存,即1000

并且,数组与指针不同, C-FAQ有一个非常好的集合,详细说明了原因 。

在可用性和行为方面的主要区别是:

  1. (1)在堆栈上,通常是Note ,而(2)总是在堆上。
  2. (1)一旦分配了固定大小,(2)可以resize。
  3. (1)在调用封闭函数时分配并且具有块范围OTOH,(2)在运行时动态分配存储器,并且返回的存储器具有从分配延伸到解除分配的寿命。
  4. (1)分配的内存不需要由程序员管理,而在(2)所有malloc() d内存应该是free() d。 [ 礼貌: Giorgi ]

注意: Wiki

例如,GNU C编译器为堆栈上的VLA分配内存。

最显着的差异是范围。 VLA数组仅在声明它的范围内有效,而动态数组将在程序中的任何位置都可用,直到您调用free()

实际上,如果编译器使用VLA的堆栈分配,则VLA可能比动态存储器更快。 但是,C标准没有规定分配VLA。

(编译器理论上可以在堆上分配VLA,但编译器也会负责清理。我不认为存在任何此类解决方案。我使用的每个编译器总是在堆栈上声明VLA。 )

这意味着VLA不适合保存大量数据:您可能会面临堆栈溢出的风险。 但是,当您使用动态内存时,这不是一个问题。

VLA不具有与动态arrays相同的可移植性,因为非常旧的编译器不支持VLA。 从理论上讲,新的C11编译器也不必支持VLA,尽管此时我知道编译器没有足够的愚蠢来放弃这种支持。


对比/总结:

  • 当存在少量本地数据时,应使用VLA,因为它们具有快速分配时间和自动清理。
  • 当存在大量数据时,应使用动态数组,以防止堆栈溢出。
  • 当数据在执行函数后需要持久存在并且可以在程序的其他地方使用时,应该使用动态数组。
  • 当您具有exception和/或无理的可移植性要求时,应使用动态数组。