动态内存访问仅在功能内部起作用 [英] Dynamic memory access only works inside function

查看:58
本文介绍了动态内存访问仅在功能内部起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此问题旨在用作此常见问题解答的规范重复:

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("\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进行调用时,则会导致程序崩溃.

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.

这是什么原因?

推荐答案

此错误的原因是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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆