malloc是不可重入的

365bet官网注册 📅 2026-02-05 01:43:54 ✍️ admin 👁️ 4973 ❤️ 250
malloc是不可重入的

线程安全不等于可重入

SO这个答案解释的很清楚

The malloc function could either be thread-safe or thread-unsafe. Both are not reentrant:

Malloc operates on a global heap, and it’s possible that two different invocations of malloc that happen at the same time, return the same memory block. (The 2nd malloc call should happen before an address of the chunk is fetched, but the chunk is not marked as unavailable). This violates the postcondition of malloc, so this implementation would not be re-entrant.

To prevent this effect, a thread-safe implementation of malloc would use lock-based synchronization. However, if malloc is called from signal handler, the following situation may happen:

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

This situation won’t happen when malloc is simply called from different threads. Indeed, the reentrancy concept goes beyond thread-safety and also requires functions to work properly even if one of its invocation never terminates. That’s basically the reasoning why any function with locks would be not re-entrant.

procps-ng 是探测/proc 的一系列软件,像top,ps之类的

top 代码在这里 https://gitlab.com/procps-ng/procps/-/blob/0bf15c004db6a3342703a3c420a5692e376c457d/top/top.c

这个patch就是典型的malloc重入bug https://gitlab.com/procps-ng/procps/-/commit/0bf15c004db6a3342703a3c420a5692e376c457d

和上面描述一毛一样

fputs(str, stderr);

exit(EXIT_FAILURE);

}

- if (Batch) fputs("\n", stdout);

+ if (Batch) {

+ write(fileno(stdout), "\n", sizeof("\n"));

}

exit(EXIT_SUCCESS);

} // end: bye_bye

bye_bye函数是信号触发的,Batch这个分支场景,进入bye_bye前是会发生malloc的,之后进入bye_bye,走到fputs,内部有malloc,发生重入,解决办法就是直接用系统调用write

参考

https://murphypei.github.io/blog/2019/07/thread-safe-reentrant-function

这里有个总结

函数体内使用了静态的数据结构

通过 malloc 和 free 来申请和释放内存,因为 malloc 是通过全局链表来管理堆的

调用了标准 I/O 库,因为库里存在大多数都是以不可重入的方式使用全局变量或者是静态变量

相关推荐

WPSWord文本框怎么组合到一起 一个操作即可
365bet官网注册

WPSWord文本框怎么组合到一起 一个操作即可

📅 10-21 👁️ 6641
揭秘《穿越火线》猎手实力榜:谁是最强猎手?他仅列第二
什么手什么庆的成语
365bet官网注册

什么手什么庆的成语

📅 07-30 👁️ 746