一个 C 语言问题, newlib 的 sprintf 是不是线程安全的?

327 天前
 xfangs

前情

newlib 是一个 C 库,经常用于嵌入式的开发中。有大佬把 newlib (4.3.0) 移植到了 switch 的自制开发环境中,这是前情。

问题

最近发现我写的一个程序使用大佬最新的 newlib (4.3.0) 依赖编译,会出现随机的蓝屏。通过查看,发现是视频播放器( libmpv )会调用 vsnprintf ,这个函数多线程调用运行不稳定。

同时通过编写示例代码,发现不仅仅是 vsnprintf ,vsprintf 、sprintf 、snprintf 在使用的时候都会出现这样的问题。

进一步分析

  1. 只有在格式化字符中包含部分格式符时才会有这个问题,比如 "%f",是因为为了计算的更精确,newlib 会在浮点数格式化时调用 _Balloc 动态申请一点内存。问题出在多线程调用 _Balloc 里。
  2. malloc 是没有问题的,我猜是因为有实现 malloc 锁
  3. 老版本(基于 4.2.0 的修改版)也是没有问题的,对比代码也没看出来啥。

我的疑问

因为这个在老版本没有问题,新版本出了问题,所以我推测可能是大佬最新版 (4.3.0) 修改版哪里没改好出的问题。

给大佬提了issue (devkitPro/newlib/issues/27),能看到大佬最近在写别的,没理我,我也没好意思继续追问(卑微~)。

想问问有 newlib 使用经验的兄弟们:

  1. sprintf 本身就不是线程安全的吗?
  2. 这个问题可能是什么原因导致的呢?
738 次点击
所在节点    问与答
3 条回复
ysc3839
327 天前
cygwin 也用的是 newlib ,并没有这种问题,所以应该是别的地方的问题
t123yh
327 天前
可以参考一下 FreeRTOS 的 configUSE_NEWLIB_REENTRANT 选项
xfangs
326 天前
@ysc3839 @t123yh 感谢,我刚刚解决了。是做修改版的大佬没有正确调用 __syscall_getreent 导致 reent 指针在不同线程是个固定的值进而在多线程下导致的问题。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/949428

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX