动态内存访问仅在函数内部有效 [英] Dynamic memory access only works inside function
问题描述
此问题旨在用作此常见问题解答的规范副本:
This question is meant to be used as a canonical duplicate for this FAQ:
我在函数内部动态分配数据,一切正常,但仅限于发生分配的函数内部.当我尝试在函数外使用相同的数据时,我会遇到崩溃或其他意外的程序行为.
I am allocating data dynamically inside a function and everything works well, but only inside the function where the allocation takes place. When I attempt to use the same data outside the function, I get crashes or other unexpected program behavior.
这是一个MCVE:
#include <stdlib.h>
#include <stdio.h>
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);
}
void print_array (int* data, int size)
{
for(int i=0; i<size; i++)
{
printf("%d ", data[i]);
}
printf("
");
}
int main (void)
{
int* data;
const int size = 5;
create_array(data, size);
print_array(data, size); // crash here
free(data);
}
每当从 create_array
函数内部调用 print_array
时,我都会得到预期的输出 0 1 2 3 4
,但是当我调用它时从 main
开始,我的程序崩溃了.
Whenever print_array
is called from inside the create_array
function, I get the expected output 0 1 2 3 4
, but when I call it from main
, I get a program crash.
这是什么原因?
推荐答案
出现这个bug的原因是create_array
函数使用的data
是一个局部变量,只存在于该函数内.从malloc
中得到的分配内存地址只保存在这个局部变量中,不会返回给调用者.
The reason for this bug is that the data
used by the create_array
function is a local variable that only exists inside that function. The assigned memory address obtained from malloc
is only stored in this local variable and never returned to the caller.
考虑这个简单的例子:
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
这里,变量a
的副本被本地存储在函数内部,作为参数x
.这称为传值.
Here, a copy of the variable a
is stored locally inside the function, as the parameter x
. This is known as pass-by-value.
当 x
被修改时,只有那个局部变量被改变.调用者中的变量a
保持不变,并且由于a
没有初始化,所以会包含垃圾",无法可靠使用.
When x
is modified, only that local variable gets changed. The variable a
in the caller remains unchanged, and since a
is not initialized, it will contain "garbage" and cannot be reliably used.
指针也不例外这个传值规则.在您的示例中,指针变量 data
按值传递给函数.函数内的 data
指针是一个本地副本,并且从 malloc
分配的地址永远不会传回给调用者.
Pointers are no exception to this pass-by-value rule. In your example, the pointer variable data
is passed by value to the function. The data
pointer inside the function is a local copy and the assigned address from malloc
is never passed back to the caller.
因此调用者中的指针变量保持未初始化状态,因此程序崩溃.此外,create_array
函数还造成了内存泄漏,因为在该函数执行后,程序中不再有任何指针来跟踪分配的内存块.
So the pointer variable in the caller remains uninitialized and therefore the program crashes. In addition, the create_array
function has also created a memory leak, since after that function execution, there is no longer any pointer in the program keeping track of that chunk of allocated memory.
有两种方法可以修改函数以使其按预期工作.通过将局部变量的副本返回给调用者:
There are two ways you can modify the function to work as expected. Either by returning a copy of the local variable back to the caller:
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);
}
或者通过将地址传递给调用者的指针变量并直接写入调用者变量:
or by passing the address to the caller's pointer variable and write directly to the caller variable:
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);
}
两种形式都可以.
这篇关于动态内存访问仅在函数内部有效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!