c - 释放指向 'double' 值的指针

标签 c pointers memory-management double free

我能找到的所有关于释放“双”指针的东西都是指释放指向指针的指针,这不是我要说的。我已经知道该怎么做了。

它甚至可能根本不是什么大事,但我注意到当我free() 一个intcharfloat 指针,该值被删除或替换为垃圾值,但是当我 free() 一个 double 指针时,该值保持不变.

这是我测试过的代码:

int main()
{
  int *p_a = malloc(sizeof(int));
  *p_a = 1;

  char *p_b = malloc(sizeof(char));
  *p_b = 'b';

  float *p_c = malloc(sizeof(float));
  *p_c = 3.565;

  double *p_d = malloc(sizeof(double));
  *p_d = 7.77;

  printf("Before 'free()':\n");
  printf("A: %p\t%d\n", p_a, *p_a);
  printf("B: %p\t%c\n", p_b, *p_b);
  printf("C: %p\t%g\n", p_c, *p_c);
  printf("D: %p\t%g\n", p_d, *p_d);

  free(p_a);
  free(p_b);
  free(p_c);
  free(p_d);

  printf("\nAfter 'free()':\n");
  printf("A: %p\t%d\n", p_a, *p_a);
  printf("B: %p\t%c\n", p_b, *p_b);
  printf("C: %p\t%g\n", p_c, *p_c);
  printf("D: %p\t%g\n", p_d, *p_d);

  return 0;
}

这产生了以下输出:

Before 'free()':
A: 0x8f2e008    1
B: 0x8f2e018    b
C: 0x8f2e028    3.565
D: 0x8f2e038    7.77

After 'free()':
A: 0x8f2e008    0
B: 0x8f2e018
C: 0x8f2e028    1.46175e-33
D: 0x8f2e038    7.77

这正常吗?我对 malloc()free() 工作原理的理解是,当你 malloc() 一个指针时,你预留了一些内存字节用于指向的指针。这是放在 heap 上,无法访问的地方,它不会从 heap 中取出,直到 free()d 或内存清理在计算机上触发,不受用户控制。因此,当您free() 一个指针时,您基本上摆脱了指针和它指向的地址之间的关联,允许稍后使用该内存。

既然如此,为什么 double 指针仍然指向相同的值?

现在我想起来了,为什么指针在 free() 之后有一个地址?

由于我是 C 的初学者,因此非常感谢任何和所有的智慧和知识。感谢您的时间。

编辑:经过进一步测试和干预后,我发现如果您输入的数字超过 6 位并在最后一位(例如 777.7777)上舍入为 double ,在 free()d 之后它会失去舍入。

举例说明:

Before 'free()':
D: 0x8f2e038    777.778

After 'free()':
D: 0x8f2e038    777.777

这支持@rodrigo 的假设(在评论中),因为 double 是 8 个字节——与 intcharfloat 的 4 个字节 - free() 仅修改前 4 个字节,因此它不会丢失所有数据。

感谢大家的帮助!

最佳答案

My understanding of how malloc() and free() work is that when you malloc() a pointer, you set aside some bytes of memory for the pointer to point to.

你不 malloc 一个指针。你 malloc 一 block 内存。 malloc 返回的值是指向该内存的指针。因此,让我们重新表述一下。

My understanding of how malloc() and free() work is that when you malloc() a block of memory, you set aside some bytes of memory; the pointer returned points to the start of that block of memory.

正确。

This [the memory block] is put on the heap

正确;将堆视为长期随机访问存储。

where it cannot be accessed

这要么是错误的,要么是荒谬的。哪些人不能访问什么

it [the block of memory] will not come off the heap until it is free()d

由 malloc 分配的内存块保留供您的程序使用,直到调用 free。要释放 block ,您调用 free 并传递最初从 malloc 返回的指针,是的。

or a memory clean-up is triggered on the computer, which is not controlled by the user

这又是不连贯的。现代操作系统使用虚拟内存。当一个进程被销毁时,整个虚拟地址空间都消失了。

when you free() a pointer, you basically get rid of the association between the pointer and the address it points to, allowing that memory to be used later on.

不不不不不。这是你误解的症结所在。

您通过将最初由 malloc 返回的指针传递给 free 来释放一 block 内存。这释放了内存块,然后允许 malloc 再次分发它,如果您的进程中的其他代码请求内存。

但是 free 不会改变指针指向的地址!指针继续指向一个地址;该地址现在无效!取消引用指向无效内存的指针在 C 语言中称为“未定义行为”,字面意思是任何 都可能发生。你的程序可能会崩溃。您可以获得曾经存在的值(value)。您的密码可以通过电子邮件发送给北极 secret 巢穴中的黑客。 任何事情都可能发生,所以不要那样做

(巧合的是,我今天早些时候写了一篇关于这个主题的博客文章,将在周三发布,所以请查看我的博客了解详情。)

Given all that, why is the double pointer still pointing to the same value?

未定义的行为意味着任何事情都可能发生。仍然指向相同值的指针是正在发生的事情,正在发生的事情是正在发生的任何事情的子集。

Now that I think about it, why do the pointers have an address at all after the free()s?

指针存储在一个变量中。 您没有更改变量的值。变量会保持其值直到您更改它们。

Where can I read more?

您可能会对这个高度相关的问题感兴趣。

Can a local variable's memory be accessed outside its scope?

这个问题和你的一样,除了在给定的问题中,指针指向堆栈,而不是堆。但逻辑是相同的:取消引用指向已弹出堆栈帧的指针是未定义的行为,就像取消引用指向已释放 block 的指针是未定义的行为一样。任何事情都有可能发生。

关于c - 释放指向 'double' 值的指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23478989/

相关文章:

c - C 中的 loadFile() 函数在执行程序时从文件加载用户

C程序调试窗口控制台不会停留

c - 数组是静态数据结构。那么内存如何动态分配给它们呢?

python - 耦合 fortran/c++ 与在 python 中调用的指针给出了段错误(核心转储)错误

arrays - Golang : process took too long. 实现拼写检查

python - 大型 PyPlot - 避免内存分配

c++ - 解除分配不会释放 Windows/C++ 应用程序中的内存

c++ - GLib HashTable 将函数作为参数传递

c++ - 为什么我在尝试计算字符串字母的程序中会出现此错误?

c++ - 常规转换与 static_cast 与 dynamic_cast