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

x86-64汇编小程序malloc时出现段错误,求解析原因

重实现strdup时malloc段错误的原因分析

问题描述

函数定义:char* _ft_strdup(const char* s);
尝试重实现strdup函数,但调用malloc时出现段错误。将pop rdi指令移到malloc调用上方后,段错误消失,想了解原因。

对应的汇编代码:

.intel_syntax
    
    extern malloc
    extern _ft_strlen
    
    section .text
        global  _ft_strdup
    
_ft_strdup:
    push    rbp         ; prologue
    mov     rbp, rsp    ; prologue
    
    push    rdi         ; save rdi value (string src)
    call    _ft_strlen  ; compute length of string src
    
    mov     rdi, rax    ; set number of bytes to allocate
    
    call    malloc      ; allocate x bytes
    
    cmp     rax, 0
    je      exit_prog
    
    pop     rdi         ; retrieve string src
    pop     rbp         ; epilogue
    ret
    
exit_prog:
    xor     rax, rax
    pop     rbp
    ret

原因分析

问题核心是栈平衡被破坏,违反了x86-64 System V调用约定的栈对齐要求:

  • x86-64的System V调用约定明确要求:调用函数前,栈必须保持16字节对齐。每次call指令会把8字节的返回地址压入栈,所以调用函数后栈的偏移会增加8字节。

  • 原代码的错误流程:

    1. 进入函数后,push rbp+mov rbp, rsp完成栈帧初始化,此时栈是对齐的。
    2. push rdi压入8字节数据,此时栈相对于rbp的偏移是16字节,仍然对齐。
    3. 调用_ft_strlen:call指令压入8字节返回地址,栈偏移变为24字节;_ft_strlen执行完毕返回后,返回地址被弹出,栈回到16字节偏移的对齐状态。
    4. 此时栈上还留着之前push rdi的8字节数据,直接调用malloc时,call又压入8字节返回地址,导致malloc执行时的栈偏移是24字节——不满足16字节对齐要求,这就是触发段错误的原因。
  • 移动pop rdi到malloc调用上方的作用:
    在调用malloc前执行pop rdi,弹出之前压入的8字节数据,此时栈相对于rbp的偏移回到8字节。调用malloc时,call压入8字节返回地址,栈偏移变为16字节,刚好符合对齐要求,malloc就能正常执行,不会触发段错误。

  • 原代码还有额外隐患:
    如果malloc返回NULL进入exit_prog分支,只会pop rbp,但之前push rdi的8字节数据还留在栈上,函数返回时会导致栈不平衡,后续代码可能出现未知错误。正确做法是在exit_prog分支里也弹出该8字节数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 11:22:12