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

如何追踪C/C++程序运行时被调用的函数与执行的语句?

C/C++ 自有代码执行流程追踪方案

1 专用追踪工具

  • uftrace
    专门用于用户态函数调用追踪的工具,刚好匹配你要替代strace/ltrace追踪自有代码的需求。使用前提就是你已经满足的-g -O0编译参数。
    基础使用流程:
  1. 执行追踪:uftrace record --filter=@/path/to/your/project/src ./你的程序 [程序参数],--filter参数可以只保留指定目录下的函数调用,自动过滤系统库、第三方库的调用
  2. 查看结果:uftrace replay即可输出结构化的调用栈、函数执行时长、调用次数等信息,也支持导出为文本、JSON等格式
    优势是性能开销极低,即使大型项目跑常规使用场景也不会有明显卡顿,支持函数级、行级追踪。
  • gcc 内置插桩(-finstrument-functions)
    不需要额外安装工具,直接通过编译参数实现函数级追踪:
  1. 编译时追加参数:-g -O0 -finstrument-functions,仅你自己编译的代码会被插桩,库函数不会被处理,天然过滤非自有代码
  2. 自行实现两个回调函数,在函数进入、退出时打印日志即可,示例代码如下:
#include <stdio.h>
#include <dlfcn.h>
void __cyg_profile_func_enter(void *this_fn, void *call_site) __attribute__((no_instrument_function));
void __cyg_profile_func_exit(void *this_fn, void *call_site) __attribute__((no_instrument_function));

void __cyg_profile_func_enter(void *this_fn, void *call_site) {
    Dl_info info;
    if (dladdr(this_fn, &info) && info.dli_sname) {
        printf("ENTER: %s\n", info.dli_sname);
    }
}
void __cyg_profile_func_exit(void *this_fn, void *call_site) {
    Dl_info info;
    if (dladdr(this_fn, &info) && info.dli_sname) {
        printf("EXIT: %s\n", info.dli_sname);
    }
}

编译时链接-ldl即可,日志可以自行输出到指定文件。

  • perf 工具
    系统自带的性能分析工具也可以实现函数调用追踪:
    执行perf record -g ./你的程序 [程序参数],运行结束后执行perf script即可输出完整的调用链,可通过符号过滤规则只保留自有项目的函数。

2 GDB 非阻塞追踪实现

你说的无需断点阻塞、仅步入自有代码、输出日志的需求完全可以通过GDB实现,具体操作如下:

  1. 提前准备GDB命令脚本,命名为trace.gdb,示例内容:
# 关闭分页,避免输出阻塞
set pagination off
# 配置日志输出路径
set logging file gdb_exec_trace.log
set logging overwrite on
set logging on

# 配置跳过非自有代码路径,不会步入这些路径下的函数
skip -gfi /usr/*
skip -gfi /lib/*
# 如有第三方依赖库,也可以配置跳过,比如:
# skip -gfi /path/to/third_party/*

# 配置追踪点动作,触发时打印当前执行信息后自动继续,不会阻塞程序
define trace-action
  # 打印当前函数名、源码路径、行号、对应代码
  frame
  continue
end

# 给自有项目下的所有函数设置非阻塞追踪点
# 替换下面的路径为你自己项目的源码根目录
rbreak /path/to/your/project/src/*:.
commands
  trace-action
end

# 启动程序
run
# 程序结束后退出GDB
quit
  1. 执行命令启动追踪:gdb -x trace.gdb --args ./你的程序 [程序参数]
  2. 程序运行结束后,所有执行记录都会保存在gdb_exec_trace.log中。

注意:如果需要语句级的执行追踪,可在上述脚本中补充步进到每一行的逻辑,不过性能开销会更高,建议只针对需要关注的模块开启。

3 方案选择建议

  • 仅需要函数级调用关系,优先选择uftrace,配置最简、性能最好,无需修改代码或编写脚本
  • 需要自定义追踪逻辑(比如打印函数参数、返回值、上下文变量),优先选择gcc内置插桩方案
  • 需要语句级执行记录,或不想安装额外工具,选择GDB追踪方案

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 22:21:01