free()不解除内存?

free(str); printf("%d\n", str->listeners); 

对printf的调用成功(对str的成员的任何其他调用也是如此)。 这怎么可能?

你只是(不)幸运。 该代码表现出未定义的行为 – 任何事情都可能发生,包括看起来没有释放内存。

内存释放,但积极清除它没有意义,因此其原始内容可能仍然存在。 但你不能依赖它。

这里有一个比喻:想象你租了一套公寓(那是记忆),然后你终止你的租约,但保留一把钥匙(这就是指针)。 如果它没有被拆除,如果没有更换锁等,你可以稍后回到公寓。如果你马上就做,你可能会发现你离开它们的方式。 但这是一个非常糟糕的主意,在可能的情况下,你会陷入一堆麻烦……

这称为未定义的行为。 您正在取消引用指向已释放内存的指针。 任何事情都可能发生,也就是说,人们不能认为程序会崩溃或其他任何事情; 行为未定义

只要str不是NULL并且相应的内存没有被其他一些分配覆盖,它仍然有效,因为内存内容不会被free更改(如果运行时没有覆盖free上的内存区域)。 但这绝对是未定义的行为,你不能依赖它以这种方式工作……

要记住的事情……

  • 在几乎所有当前的操作系统上, free()永远不会将内存返回给操作系统。 即使它在理论上能够做到这一点,它几乎从未真正发生过。 这是因为内存只能在4kB的对齐页面中返回,因为这就是MMU的工作原理,并且,如果找到一个,将其删除可能会破坏包含内存和下方内存的块,使整个过程适得其反。 (碎片化是有效使用动态内存的敌人。)
  • 此外,大多数程序通常只使用更多内存,因此搜索某些内容以真正返回操作系统所花费的时间将完全被浪费掉。 如果它没有返回给操作系统然后受到保护,那么当你触摸它时它不会核心你的程序。
  • 所以相反,你给free的块只是放在一个列表或其他数据结构上,然后可能合并到它上面或下面的块中。
  • 内存仍然存在且可访问。 某些块可能被指针和malloc()和free()后面的库代码的其他内部覆盖。 但它可能不是。
  • 最终它可能会在您的程序中的其他位置返回。 但它可能不是。