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_array
从create_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都很好。