“释放”malloc“返回的指针是否总是安全的?

Is it always safe to `free` a pointer returned by `malloc`?

提问人:Maciek 提问时间:9/28/2023 更新时间:9/29/2023 访问量:127

问:

我的理解是,只有当已知两个函数在同一堆上运行时,才允许使用调用返回的指针(或任何其他函数返回指向堆上动态分配的某个内存的指针,如或)进行调用。因此,我理解“一般方法”应该是提供一个互补的释放例程,而不是调用我们从分配它的函数返回的任何指针,因为在一般情况下,我们永远不知道指针是否已经通过任何可以影响它的边界。我认为直接调用我们被提交的指针应该更像是一种特例,当我们确定我们持有的指针对我们来说是安全的(例如,我们 -ed 或它自己,或者我们知道分配它的例程在某个地方“接近”并且指针没有通过任何边界)。freemallocstrdupasprintffreefreefreestrdupmalloced

然而,我已经很久没有做过任何专业的 C 了,当我做过的时候,它并不多,所以我只能知道错了。我遇到了许多观点,即调用任何(有效的、未释放的)恶意指针通常是安全的,并且只有在明确知道有必要时才应使用自定义释放例程。但这在某种程度上与我在 Windows 上使用 Visual Studio 6 的记忆形成了鲜明的对比,在 Windows 上,调用任意已知的恶意指针的成功取决于在“静态/动态链接的运行时”、“调试/发布版本”和“单线程/多线程运行时”的三维兼容性矩阵中分配和解除分配方的位置。freefree

那么我的问题是:调用指针的一般和实用规则是什么,我肯定知道已经是 -ed,而不是 -d?什么时候是安全的,更重要的是,什么时候不安全?如果我创建一个返回 -ed 指针的函数,我是否应该始终提供一个单独的函数来释放它,或者(在一般情况下)是否足以说“通过在我刚刚返回给你的指针上调用 free 来释放返回的内存”?从实际的角度来看,遇到调用不兼容堆并对其进行操作,或者以任何其他方式不对称的情况的可能性有多大?让我们假设指针指向一些微不足道的数据,而不是一些不透明的结构,该结构包含一些额外的簿记信息,并且需要一些复杂的逻辑来释放使用的内存。freemallocfreemallocmallocfree

c malloc 免费 分配

评论

3赞 Barmar 9/28/2023
只有一个堆被所有人使用,并调用。还有其他分配内存的方法,例如 .但是,如果内存是用 分配的,则可以安全地使用 释放它。malloc()free()mmap()malloc()free()
1赞 Barmar 9/28/2023
如果函数返回指针,则文档应说明调用方是否应释放它。
1赞 Weather Vane 9/28/2023
您可以使用 释放它一次。如果您对事件的顺序有疑问,则可以设置可以安全传递到的指针(如果您继续取消引用它,这将产生一个明显的可识别问题)。free()NULLfree()
0赞 Barmar 9/28/2023
一些库提供了自己的“清理”功能,该函数负责释放任何应该释放的内容。同样,文档应该解释你应该如何处理返回的数据。
1赞 Andrew Henle 9/28/2023
@Barmar OP 可能被 Microsoft 的运行时库混淆了,这些库反常地可以而且确实使用多个堆。stackoverflow.com/questions/10820114/......仅举一个例子。

答:

1赞 0___________ 9/28/2023 #1

遇到调用 malloc 并自由操作的情况 不兼容的堆,或者以任何其他方式不对称?让我们 假设指针指向一些微不足道的数据,而不是 到一些不透明的结构,其中包含一些额外的簿记 信息,并且需要一些复杂的逻辑来释放使用的 记忆。

该语言对堆一无所知。它只知道对象的存储持续时间。由族函数创建的对象已分配存储持续时间分配的存储持续时间对象一直存在,直到通过调用函数释放该对象。因此,符合要求的程序应该对任何内存安全Cmallocfreefreemalloc

如果您的程序不符合要求,并且使用了许多不同的实现(即动态库使用与主程序不同的实现),那么很明显,您的主程序不应该用于由 的不同实现 分配的对象。mallocfreemalloc

4赞 chux - Reinstate Monica 9/28/2023 #2

...调用的一般和实用规则是什么......?
什么时候是安全的,更重要的是,什么时候不安全?
free

free(NULL)总是好的。

否则:

  • 在来自的任何指针上调用一次 ,都是可以且定义良好的。free()malloc(), calloc(), realloc(), strdup(), aligned_alloc()

  • 释放指针后,不要再次释放它。

  • 不要尝试取消引用自由指针。

  • 使用这些函数,不存在不兼容的问题。

  • 不要调用源自其他地方的其他指针。free()

评论

1赞 chqrlie 9/28/2023
您可以添加: 不要取消引用已释放的指针:访问已释放块中的内存具有未定义的行为。
1赞 chux - Reinstate Monica 9/28/2023
@chqrlie好吧,即使复制一个免费的指针也是技术性的UB,但我不想死在那座山上,所以这里只提到它。
0赞 0___________ 9/29/2023
@chux-ReinstateMonica 我想他是在问奇怪的 Windows 库:)
1赞 R-Rothrock 9/29/2023 #3

请注意,这是在 Linux 上。我不知道 VSC 是否/如何不同。Library Functions Manual

The free() function frees the memory space pointed to by ptr, which must have
been returned by a previous call to malloc() or related functions. Otherwise,
or if ptr has already been freed, undefined behavior  occurs. If ptr is NULL,
no operation is performed.

TLDR 是的,只要您每个指针的执行次数不超过一次。