为什么将malloc()和printf()称为不可重入?
转载自https://mlog.club/article/1807704
在unix系统中,我们知道malloc()是一个不可重入的函数(系统调用)。为什么?
类似地,printf()也被认为是不可重入的;为什么?
我知道重新进入的定义,但我想知道为什么它适用于这些功能。
是什么阻止了它们被保证可重入?
最佳答案:
malloc和printf通常使用全局结构,并在内部使用基于锁的同步。这就是为什么它们不可重入。
malloc函数可以是线程安全的,也可以是线程不安全的。两者都不可重入:
malloc在全局堆上操作,同时发生的两个不同的malloc调用可能返回相同的内存块。(第二个malloc调用应该在获取块的地址之前发生,但块没有标记为不可用)。这违反了malloc的后置条件,因此此实现不会重新进入。
为了防止这种影响,线程安全的malloc实现将使用基于锁的同步。但是,如果从信号处理程序调用malloc,则可能发生以下情况:
malloc(); //initial call
lock(memory_lock); //acquire lock inside malloc implementation
signal_handler(); //interrupt and process signal
malloc(); //call malloc() inside signal handler
lock(memory_lock); //try to acquire lock in malloc implementation
// DEADLOCK! We wait for release of memory_lock, but
// it won't be released because the original malloc call is interrupted
当从不同线程调用malloc时,这种情况不会发生。实际上,可重入性概念超出了线程安全的范畴,还要求函数正常工作,即使其中一个调用从未终止。这就是为什么任何带有锁的函数都不会重新进入的原因。
printf函数也对全局数据进行操作。任何输出流通常都使用一个附加到资源数据的全局缓冲区(用于终端或文件的缓冲区)。打印过程通常是将数据复制到缓冲区,然后刷新缓冲区的序列。这个缓冲区应该像malloc那样被锁保护。因此,printf也是不可重入的。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义