为什么我必须free
使用malloc创建的数组,而不是使用初始化程序创建的数组?
float* rgba = malloc(4 * sizeof(float));
free(rgba);
与
float rgba[] = { 0.0f, 0.0f, 0.0f, 0.0f };
free(rgba); // ERROR
第二部分内幕发生了什么?
答案 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
取消分配本地和静态内存。它根本无法取消分配。您没有本地或静态内存,这意味着您的业务不用担心其重新分配。本地和静态对象具有遵循预定规则的预定寿命。它们是完全按照这些规则自动创建和销毁的。
在第一种情况下,你根本没有真正声明一个数组。您正在声明指向动态分配的内存块的指针。您拥有动态分配的所有内存块,这意味着您有责任正确释放它们。