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

memcpy异常场景下backtrace()调用崩溃,如何实现安全调用?

问题原因分析

你遇到的二次崩溃本质是堆结构已被破坏导致的:当memcpy传入-1作为size时,由于size_t是无符号类型,这个值会被解析成极大的内存长度,触发大规模越界内存写入,直接破坏了malloc管理的堆元数据。此时在信号处理函数crit_err_hdlr中调用backtrace,而多数libc的backtrace实现会隐式调用malloc(比如分配临时存储),但堆已经损坏,malloc检测到无效的堆结构,直接触发二次崩溃。

而空指针写入的场景中,堆结构未被破坏,所以backtrace可以正常调用malloc完成栈回溯。

安全调用backtrace的解决方案
  • 避免在信号处理函数中调用非异步信号安全的函数
    POSIX标准明确规定,信号处理函数只能调用异步信号安全的函数(比如write、_exit等),malloc、backtrace、backtrace_symbols都不在这个列表里。直接在信号处理函数里调用这些函数本身就存在风险,尤其是堆已损坏的场景。

  • 预分配栈回溯缓冲区
    把存储栈帧的void* array从信号处理函数的局部变量改为全局预分配的数组,避免在信号处理时触发栈上的内存分配(虽然栈分配本身是安全的,但全局分配更稳妥):

    // 全局预分配栈回溯缓冲区
    #define BACKTRACE_SIZE 10
    void* g_backtrace_array[BACKTRACE_SIZE];
    
    void crit_err_hdlr(int sig_num, siginfo_t * info, void * ucontext)
    {
        size_t size = backtrace(g_backtrace_array, BACKTRACE_SIZE);
        // 后续处理
    }
    
  • 使用backtrace_symbols_fd替代backtrace_symbols
    如果需要解析栈帧为符号,不要用backtrace_symbols(它会调用malloc分配字符串数组),改用backtrace_symbols_fd,它直接将符号信息写入指定的文件描述符(比如STDERR_FILENO或预先打开的日志文件),完全避免malloc调用:

    void crit_err_hdlr(int sig_num, siginfo_t * info, void * ucontext)
    {
        size_t size = backtrace(g_backtrace_array, BACKTRACE_SIZE);
        // 直接写入标准错误或日志文件
        backtrace_symbols_fd(g_backtrace_array, size, STDERR_FILENO);
    }
    
  • 为信号处理函数分配独立栈
    如果必须在信号处理中执行复杂操作,可以通过sigaltstack为信号处理函数设置独立的栈空间,避免原栈或堆损坏影响信号处理的执行:

    void backtrace_init() {
        struct sigaction sigact;
        stack_t sigstack;
    
        // 分配独立的信号栈
        sigstack.ss_sp = malloc(SIGSTKSZ);
        sigstack.ss_size = SIGSTKSZ;
        sigstack.ss_flags = 0;
        sigaltstack(&sigstack, NULL);
    
        sigact.sa_sigaction = crit_err_hdlr;
        sigact.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK; // 指定使用独立栈
        sigaction(SIGSEGV, &sigact, NULL);
    }
    

    注意:这里的malloc要在程序初始化时调用,此时堆结构是完好的,不会有问题。

  • 从源头避免堆破坏
    在调用memcpy等内存操作函数前,严格校验参数合法性,比如确保size不超过目标缓冲区的长度,避免传入负数或过大的无符号值,从根源减少堆损坏的场景。

内容的提问来源于stack exchange,提问作者Андрей Виноградов

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 20:40:13