严格来说,C 标准是不是要求 free 必须在 malloc 之后调用,当不满足这个要求时它规定了啥?

Posted

技术标签:

【中文标题】严格来说,C 标准是不是要求 free 必须在 malloc 之后调用,当不满足这个要求时它规定了啥?【英文标题】:Strictly speaking, does the C standard require that free must be called after malloc and what does it prescribe when this requirement is not met?严格来说,C 标准是否要求 free 必须在 malloc 之后调用,当不满足这个要求时它规定了什么? 【发布时间】:2018-03-25 21:05:29 【问题描述】:

来自http://en.cppreference.com/w/c/memory/malloc:

返回的指针必须用 free() 或 realloc() 释放。

来自http://en.cppreference.com/w/c/memory/calloc:

返回的指针必须用 free() 或 realloc() 释放。

严格来说,为什么必须释放返回的指针?

现在我知道 POSIX 要求在程序终止时释放内存,因此在实践中调用 malloc 并立即终止不会造成任何伤害。但这不是我要问的。

C 标准中是否存在这种硬性要求(“必须释放”),或者这是 cppreference 贡献者的发明,以敦促程序员不要泄漏内存?如果标准中存在这样的硬性要求,这是否意味着,根据 C 标准(除了 POSIX 和其他与操作系统相关的东西!),如果 malloc 返回的指针不是 free,则程序是 UB d,或者标准是否定义了未能满足此要求的后果? (这将特别有趣,因为这可能意味着标准处理程序已经终止时发生的事情!)

【问题讨论】:

在某些永不终止的嵌入式应用程序中,您可能调用 malloc(),但从不调用 free() 来构建将永远存在的内部数据结构,或者更确切地说,直到有人拉电源线。所以在这种情况下,不可能满足要求来释放分配的内存块 我一直读到这句话说“如果你想释放内存,你必须使用free()realloc()”。 我认为重点不在“必须”,而在“免费”。当块被释放时,必须使用函数free 另见答案Should I free memory before exit?, C 标准中没有引用的段落。我也找不到类似的东西。 【参考方案1】:

当他们在 cppreference.com 上说“返回的指针必须用 free 释放”时,他们并不意味着程序员必须这样做。它的意思更多的是“当分配的内存被释放时,必须使用 free 或 realloc 来完成,因为只有那些函数才能正确地完成它。”在实际规范中没有这样的命令。

【讨论】:

【参考方案2】:

C 不要求您在分配后释放()内存。

副作用是内存泄漏。但是您永远不会看到任何错误或警告。这是你作为程序员的工作来解决。

【讨论】:

【参考方案3】:

虽然realloc()free() 是C 中最自然的释放内存的方式,但在C++ 中最自然的释放内存的方式是delete。虽然链接的页面描述了 C 中的行为,但该语言与描述 C++ 中的行为的页面是平行的:

成功时,返回指向新分配内存开头的指针。返回的指针必须用 std::free() 或 std::realloc() 释放。

我怀疑描述 C++ 的文本的预期目的是明确其他释放存储的方式,包括delete,不适用于从std::mallocstd::calloc 接收的存储;即使 C 缺少任何其他预期可以工作的方式,相同的文本也会出现在描述 C 中。

【讨论】:

我不知道,也许有人会想到使用负值的munmapsbrk 而不是free?不过我觉得这不太可能 @gaazkam:实现可以提供其他释放内存的方法,但 free 和 realloc() 是标准提供的仅有的两个。 在 malloc 之后使用 sbrk 会导致未定义的行为:pubs.opengroup.org/onlinepubs/7908799/xsh/brk.html @mnistic:这是 Unix 或其他实现 sbrk 的系统的问题; C 标准对此类函数只字未提。 @supercat 当然,这就是为什么一开始就将两者混为一谈是个坏主意,但 The Open Group 的好人一定要明确说明【参考方案4】:

不,绝对不需要释放任何内存。这样做是为了您自己,允许实现再次使用它来满足未来对 malloc 的调用。

此外,C 对 C 程序之外或终止后的机器/操作系统的状态没有任何可说的。指定这取决于操作系统或管理它的标准,实际上对于任何多进程操作系统,malloc 获得的内存和其他类似资源都会在进程终止时消失。

【讨论】:

我同意 C 标准不要求您释放内存,但是在程序终止后它对您的机器状态无话可说的评论与弄清楚这一点无关。 C 标准可以指定一个程序在没有释放分配的内存的情况下终止会产生一些错误消息,或者它在退出时的行为是未定义的,等等。也就是说,从理论上讲,该标准可以强制要求释放内存,而无需强制任何终止后要求。 @EricPostpischil:第二段更多地解决了“依赖操作系统在程序结束时释放所有内容”是“不可移植”很重要的常见误解。第一段已经解决了对free的任何要求。【参考方案5】:

语句返回的指针必须用free()或realloc()释放在C11 standard draft n1570中不存在。

严格来说,标准并没有说对象必须被释放。它甚至没有明确说明内存块需要由freerealloc 释放 - 只是该标准没有提供任何可用于释放空间的其他函数.

但是,也不能保证它们在程序退出时被释放——相反,所有的语言都为通过main 输入的程序提供了不调用@ 仍然可能泄漏内存的可能性。 987654327@,并且仍然在符合要求的实现上运行。标准在6.2.4p2中说:

2 对象的生命周期是程序执行部分,在此期间保证为它保留存储空间。一个对象存在,具有一个常量地址,33) 并在其生命周期内保留其最后存储的值。34) 如果一个对象在其生命周期之外被引用,则行为未定义。当指针指向(或刚刚过去)的对象到达其生命周期的末尾时,指针的值变得不确定。

在7.22.3p1:

已分配对象的生命周期从分配一直延续到解除分配。

就是这样。 C 标准不关心在程序执行终止后发生的任何事情。这是由于遗漏而未定义的行为,因此任何一种可能的行为都是符合标准的。

【讨论】:

以上是关于严格来说,C 标准是不是要求 free 必须在 malloc 之后调用,当不满足这个要求时它规定了啥?的主要内容,如果未能解决你的问题,请参考以下文章

严格标准错误

new和malloc的区别

C语言中已经有了malloc和free,为啥还需要new和delete?

C/C++常见面试题

C/C++常见面试题

C/C++ 面试题记录