使用malloc和数组初始值设定项之间的区别?

时间:2013-12-16 03:32:20

标签: c arrays malloc free initializer

为什么我必须free使用malloc创建的数组,而不是使用初始化程序创建的数组?

float* rgba = malloc(4 * sizeof(float));
free(rgba);

float rgba[] = { 0.0f, 0.0f, 0.0f, 0.0f };
free(rgba); // ERROR

第二部分内幕发生了什么?

5 个答案:

答案 0 :(得分:2)

在第一种情况下:

堆内存段中有分配。无论在堆中分配的是什么,都必须由用户取消分配。编译器不负责自动解除分配。

在第二种情况下:

内存分配发生在堆栈或数据段中,具体取决于您是在函数内部还是全局分配数组!

如果在函数外部分配数组,则会在内存的数据段部分进行分配。

如果你在函数内部分配了它在堆栈中分配的数据。

无论在堆栈或数据段中分配的是什么,都会自动取消分配。无需从用户端进行明确的解除分配。

答案 1 :(得分:1)

不同之处在于malloc始终从动态内存中分配内存,而初始化程序将数据放在静态或自动内存中,具体取决于您定义的上下文rgba

  • 如果您的定义超出任何功能,或者您将static添加到定义中,则会在静态区域中分配rgba,并获得静态或全局可见性
  • 如果声明在函数内部,则内存将在自动区域中分配(也称为“在堆栈中”)。

由于free的调用只能传递来自malloc系列(malloc / calloc / realloc)或其他函数的函数返回的指针返回动态内存(例如strdup),在非malloc-ed指针上调用free是未定义的行为。

答案 2 :(得分:0)

因为

float rgba[] = { 0.0f, 0.0f, 0.0f, 0.0f };

这里数组内存在堆栈上分配。当程序超出范围时,编译器本身会释放该内存。如果你释放它,编译器将释放它,它将是双重免费的情况。

在第一个中,您将内存分配给堆。用户负责释放用户分配的堆内存。这就是为什么free在第一种情况下会起作用的原因。

答案 3 :(得分:0)

第一种情况是动态分配内存,其中内存分配在内存的部分。这意味着内存分配是在编译后的运行时完成的。

第二种情况是正常的局部变量创建,其中内存在编译期间在内存的堆栈部分中分配。

free()函数用于取消分配在仅运行时期间分配的内存,而不是编译时。因此你会收到错误。

答案 4 :(得分:0)

首先,您的任何示例中都没有“指定的初始值设定项”。您的第二个示例使用聚合初始化程序语法,而没有任何实际的初始值设定项被“指定”。

其次,这对于聚合初始化器没有任何影响。主要区别在于左侧:第一种情况为float* rgba,第二种情况为float rgba[]

在第二种情况下,您实际上是声明一个数组,它是一个本地或静态数组(取决于该声明所在的位置)。不应使用free取消分配本地和静态内存。它根本无法取消分配。您没有本地或静态内存,这意味着您的业务不用担心其重新分配。本地和静态对象具有遵循预定规则的预定寿命。它们是完全按照这些规则自动创建和销毁的。

在第一种情况下,你根本没有真正声明一个数组。您正在声明指向动态分配的内存块的指针。您拥有动态分配的所有内存块,这意味着您有责任正确释放它们。