gpt4 book ai didi

c - 动态内存访问仅在函数内部有效

转载 作者:太空狗 更新时间:2023-10-29 16:29:49 25 4
gpt4 key购买 nike

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

我在函数内部动态分配数据,一切正常,但仅在进行分配的函数内部。当我尝试在函数外部使用相同的数据时,我遇到了崩溃或其他意外的程序行为。

这是一个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("\n");
}

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,我遇到程序崩溃。

这是什么原因?

最佳答案

出现这个bug的原因是create_array函数使用的data是一个只存在于该函数内部的局部变量。从malloc获得的分配内存地址只保存在这个局部变量中,不会返回给调用者。


考虑这个简单的例子:

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 本地存储在函数内部。这称为按值传递

x 被修改时,只有那个局部变量被改变。调用者中的变量a保持不变,由于a没有初始化,它会包含“垃圾”,不能可靠地使用。


指针也不异常(exception)。在您的示例中,指针变量 data 按值传递给函数。函数内的 data 指针是本地副本,从 malloc 分配的地址永远不会传回给调用者。

因此调用者中的指针变量保持未初始化状态,因此程序崩溃。此外,create_array 函数还造成了内存泄漏,因为在该函数执行后,程序中不再有任何指针跟踪分配的内存块.


您可以通过两种方式修改函数以使其按预期工作。通过将局部变量的副本返回给调用者:

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);
}

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

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);
}

任何一种形式都可以。

关于c - 动态内存访问仅在函数内部有效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39486797/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com