dynamic内存访问只在函数内部起作用

此问题旨在用作此常见问题的规范副本:

我在一个函数内dynamic分配数据,一切正常,但只在分配发生的函数内。 当我尝试在函数外部使用相同的数据时,出现崩溃或其他意外的程序行为。

这是一个MCVE:

#include <stdlib.h> #include <stdio.h> void print_array (int* data, int size) { for(int i=0; i<size; i++) { printf("%d ", data[i]); } printf("\n"); } void create_array (int* data, int size) { data = malloc(sizeof(*data) * size); for(int i=0; i<size; i++) { data[i] = i; } print_array(data, size); } int main (void) { int* data; const int size = 5; create_array(data, size); print_array(data, size); // crash here } 

每当print_arraycreate_array函数中调用,我得到期望的输出0 1 2 3 4 ,但是当我从main调用它,我得到一个程序崩溃。

这是什么原因?

这个bug的原因是create_array函数使用的data是只存在于该函数中的局部variables。 从malloc获取的分配的内存地址只存储在本地variables中,永远不会返回给调用者。


考虑这个简单的例子:

 void func (int x) { x = 1; printf("%d", x); } ... int a; func(a); printf("%d", a); // bad, undefined behavior - the program might crash or print garbage 

这里,variablesa一个副本被存储在函数内部,作为参数x 。 这被称为通过价值

x被修改时,只有该局部variables被改变。 调用者中的variablesa保持不变,并且由于a未被初始化,所以将包含“垃圾”并且不能被可靠地使用。


指针也不例外,这是按值传递的规则。 在你的例子中,指针variablesdata通过值传递给函数。 函数内的data指针是一个本地副本,从malloc分配的地址永远不会传回给调用者。

所以在调用者的指针variables保持未初始化,因此程序崩溃。 另外, create_array函数也创build了内存泄漏 ,因为在该函数执行之后,程序中不再有任何指针来跟踪该分配的内存块。


有两种方法可以修改函数以按预期方式工作。 通过返回本地variables的副本返回给调用者:

 int* create_array (int size) { int* data = malloc(sizeof(*data) * size); for(int i=0; i<size; i++) { data[i] = i; } print_array(data, size); return data; } int main (void) { int* data; const int size = 5; data = create_array(size); print_array(data, size); } 

或通过将地址传递给调用者的指针variables并直接写入调用者variables:

 void create_array (int** data, int size) { int* tmp = malloc(sizeof(*tmp) * size); for(int i=0; i<size; i++) { tmp[i] = i; } *data = tmp; print_array(*data, size); } int main (void) { int* data; const int size = 5; create_array(&data, size); print_array(data, size); } 

这两种forms都很好。