You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

共享库-fini函数可调用哪些函数?LD_PRELOAD下printf调用失败问题

LD_PRELOAD共享库的-fini函数中printf调用失败的原因及可用函数说明

问题原因

程序进入退出流程时,glibc的执行顺序决定了共享库的-fini函数是在C标准库核心组件清理之后才执行。具体流程大致为:

  1. 执行atexit/on_exit注册的回调函数
  2. 刷新并关闭所有stdio流(包括stdout)
  3. 调用各个共享库的fini函数
  4. 最终调用_exit系统调用终止进程

你的示例中,fini函数执行时,stdout已经被关闭,printf依赖的stdio流结构已被销毁,因此调用失败返回-1,触发了后续的sleep(2)。而sleep是直接封装内核系统调用的函数,不依赖C标准库的全局状态,所以能正常执行。

-fini函数中可安全调用的函数范围

在fini函数中,只能调用不依赖C标准库已销毁资源的函数,主要包括:

  • 直接映射系统调用的函数:比如write、read、sleep、_exit、getpid等(注意使用write时要直接操作文件描述符,如STDOUT_FILENO,而非依赖stdio流)
  • 纯逻辑计算类函数:不涉及内存分配、IO操作的自实现函数或标准库函数(如strlen这类无状态函数)
  • 不依赖全局初始化状态的函数:避免使用任何需要C标准库全局结构支持的功能,比如printf/fprintf等stdio家族函数、malloc/free堆操作函数、线程相关函数(线程库可能已完成清理)

修复示例

将fini函数中的printf替换为直接调用write,即可正常输出内容:

#include <stdio.h>
#include <unistd.h>
#include <string.h>

void init() {   
    printf("%s\n", __func__);
    fflush(stdout);
}

void fini() {
    const char msg[] = "fini\n";
    write(STDOUT_FILENO, msg, strlen(msg));
    sleep(2);
}

执行修改后的代码,会正常输出init、mark和fini,同时保留2秒停顿。

内容的提问来源于stack exchange,提问作者Mark Galeck

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 08:15:35