”返回在函数内malloc的内存是安全的,但是容易造成问题,最好的做法是返回传入的指针。“怎么理解?

翁恺老师在返回函数的指针中说:'返回在函数内malloc的内存是安全的,但是容易造成问题, 最好的做法是返回传入的指针。'怎么理解这句话?
关注者
26
被浏览
11,283

12 个回答

被调用的函数(callee)分配的内存,调用方(caller )是不清楚应该怎么释放(甚至要不要释放)的。

如果你观察 C 的标准库函数接口也会发现,他们尽量不在内部分配内存。

如果一定要 callee 来分配内存,也应该由 callee 同一模块的函数来释放内存。

举个例子。我曾经遇到过个堆错误导致崩溃的 bug,经过一番调试和网上搜索,发现问题出在我把 `std::string` 对象传递过了库的边界,碰巧 `std::string` 又是移动构造的。这导致内存由库分配,由调用库的应用释放。库和应用使用的是不同的 vcruntime 实例,堆的状态有两份,就导致了 assert 失败。

从逻辑上来说,如果资源是某一方分配的,也应该由它来释放,只有它知道状态是怎么管理的,分配释放有什么内部机制(甚至将来你想做什么优化,比如用上池,都得这样设计接口才好改)。

我的理解:

“返回在函数内malloc的内存是安全的” 这句话是指,返回在函数内栈分配的内存地址是不安全的,相比较而言,返回在函数内由malloc分配的堆内存地址是相对安全的。

“但是容易造成问题” 是指,你一个函数malloc了一块内存并返回到外部,那么就需要在外部去delete它,否则就会产生内存泄露,同时如果你的malloc是在函数内的某个逻辑分支中才发生,那么你在外面delete的时候就得有相应的判断,否则容易产生double delete的问题。

“最好的做法是返回传入的指针” 这个说法我觉得不妥,更合理的表达可能是 “函数最好不要改变它涉及的资源,既不要将新建的资源返回到外部,也不要将传入的资源回收掉”。在所有函数都不改变其依赖的资源的情况下,程序固然更容易推理,也更容易被正确地实现,但是是否能这么做却是要看业务场景的。