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

x86_64 Intel汇编中释放结构体指针触发SEGV崩溃问题

问题分析与修复

你的汇编代码崩溃的核心原因是调用函数前未遵守x86_64栈对齐约定,同时存在多余的栈操作和逻辑缺陷,具体如下:

1. 栈对齐错误(崩溃直接原因)

x86_64 SysV调用约定要求:调用任何函数前,rsp必须是16字节的倍数。你的代码在调用free时,rsp处于8字节对齐状态,违反了该约定。macOS和新版Debian对栈对齐要求严格,会触发SEGV;旧Linux Mint可能容忍不对齐,因此之前能正常运行。

同时,调用free时你额外push r11是完全多余的——free只需要rdi参数,你已经将待释放的节点指针存入rdi,无需再压栈保存r11。这行多余的代码进一步破坏了栈对齐。

2. 逻辑缺陷:未处理头节点删除

原代码仅检查并删除当前节点的下一个节点,完全忽略了头节点本身的匹配情况。如果头节点需要被删除,代码不会处理,导致内存泄漏或后续访问错误。

修复后的代码

global _ft_list_remove_if
extern free

section .text

_ft_list_remove_if:
    push rbp
    mov rbp, rsp
    sub rsp, 40         ; 预留空间保存参数和临时寄存器
    mov QWORD [rsp], rdi        ; 保存begin_list指针
    mov QWORD [rsp + 8], rsi    ; 保存data_ref
    mov QWORD [rsp + 16], rdx   ; 保存cmp函数指针
    mov QWORD [rsp + 24], rcx   ; 保存free_fct函数指针

    mov r10, QWORD [rdi]        ; r10 = 当前节点(初始为头节点)
    mov r11, 0                  ; r11 = 前驱节点(初始为0,代表头节点无前驱)

.check_head:
    cmp r10, 0
    je .restore_stack

    ; 调用cmp函数检查当前节点是否匹配
    mov rdx, QWORD [rsp + 16]
    mov rsi, QWORD [rsp + 8]
    mov rdi, QWORD [r10]
    ; 用栈帧保存寄存器,避免push/pop破坏栈对齐
    mov QWORD [rbp - 8], r10
    mov QWORD [rbp - 16], r11
    call rdx
    ; 恢复寄存器
    mov r10, QWORD [rbp - 8]
    mov r11, QWORD [rbp - 16]

    cmp eax, 0
    jne .move_to_next

    ; 当前节点需要删除
    mov rax, QWORD [r10 + 8]    ; rax = 当前节点的next指针
    cmp r11, 0
    je .delete_head             ; 无前驱,说明是头节点

    ; 处理中间节点:更新前驱节点的next
    mov QWORD [r11 + 8], rax
    jmp .delete_node

.delete_head:
    ; 更新链表头指针(*begin_list)
    mov QWORD [rdi], rax

.delete_node:
    ; 释放节点的data
    mov rcx, QWORD [rsp + 24]
    mov rdi, QWORD [r10]
    mov QWORD [rbp - 8], r10
    mov QWORD [rbp - 16], r11
    call rcx
    mov r10, QWORD [rbp - 8]
    mov r11, QWORD [rbp - 16]

    ; 释放节点本身
    mov rdi, r10
    call free wrt ..plt         ; Linux环境用该行;macOS改为call _free

    ; 删除后直接跳到下一个节点
    mov r10, rax
    jmp .check_head

.move_to_next:
    ; 无需删除,移动到下一个节点,更新前驱
    mov r11, r10
    mov r10, QWORD [r10 + 8]
    jmp .check_head

.restore_stack:
    add rsp, 40
    pop rbp
    ret

修复说明

  1. 栈对齐修复:使用rbp偏移的栈帧保存临时寄存器,避免push/pop破坏rsp对齐,确保调用外部函数前rsp始终是16字节倍数。
  2. 移除多余操作:删除调用free时冗余的push r11和pop r11操作,精简栈操作逻辑。
  3. 头节点处理:新增头节点检查分支,当头节点匹配时,直接更新传入的*begin_list指针,保证链表头正确更新。
  4. 遍历逻辑优化:改为检查当前节点而非下一个节点,确保所有节点(包括最后一个)都能被处理,避免遗漏。

编译注意事项

  • Linux环境:将函数名改为ft_list_remove_if(去掉下划线),保留call free wrt ..plt。
  • macOS环境:函数名保留_ft_list_remove_if,将call free wrt ..plt替换为call _free。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 14:39:50