V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
xfangs
V2EX  ›  问与答

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

  •  
  •   xfangs · 2023-06-16 22:49:20 +08:00 · 930 次点击
    这是一个创建于 507 天前的主题,其中的信息可能已经有所发展或是发生改变。

    前情

    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. 这个问题可能是什么原因导致的呢?
    3 条回复    2023-06-17 14:36:49 +08:00
    ysc3839
        1
    ysc3839  
       2023-06-17 03:12:02 +08:00 via Android
    cygwin 也用的是 newlib ,并没有这种问题,所以应该是别的地方的问题
    t123yh
        2
    t123yh  
       2023-06-17 08:22:54 +08:00
    可以参考一下 FreeRTOS 的 configUSE_NEWLIB_REENTRANT 选项
    xfangs
        3
    xfangs  
    OP
       2023-06-17 14:36:49 +08:00
    @ysc3839 @t123yh 感谢,我刚刚解决了。是做修改版的大佬没有正确调用 __syscall_getreent 导致 reent 指针在不同线程是个固定的值进而在多线程下导致的问题。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5528 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 08:35 · PVG 16:35 · LAX 00:35 · JFK 03:35
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.