Venus模拟器中调用free系统调用的RISC-V代码无法终止问题
Venus模拟器中调用free后代码无法终止的问题分析与解决
我从大型代码中隔离出以下简易RISC-V代码,其中malloc和free的实现取自伯克利CS61C 2020秋季项目2:
.globl main # we have a0, a1, a2 main: addi sp, sp, -36 sw s0, 0(sp) sw s1, 4(sp) sw s2, 8(sp) sw s3, 12(sp) sw s4, 16(sp) sw s5, 20(sp) sw s6, 24(sp) sw s7, 28(sp) sw s8, 32(sp) addi sp, sp, -24 sw ra, 8(sp) sw a0, 12(sp) sw a1, 16(sp) sw a2, 20(sp) li a0, 4 jal ra, malloc mv s0, a0 lw ra, 8(sp) lw a0, 12(sp) lw a1, 16(sp) lw a2, 20(sp) addi sp, sp, 24 # cleaning m0 addi sp, sp, -16 sw a0, 0(sp) sw a1, 4(sp) sw a2, 8(sp) sw ra, 12(sp) mv a0, s0 jal ra, free lw a0, 0(sp) lw a1, 4(sp) lw a2, 8(sp) lw ra, 12(sp) addi sp, sp, 16 #Epilog lw s0, 0(sp) lw s1, 4(sp) lw s2, 8(sp) lw s3, 12(sp) lw s4, 16(sp) lw s5, 20(sp) lw s6, 24(sp) lw s7, 28(sp) lw s8, 32(sp) addi sp, sp, 36 ret free: mv a1 a0 li a0 0x3CC addi a6 x0 4 ecall ret malloc: mv a1 a0 li a0 0x3CC addi a6 x0 1 ecall ret
这段代码在Venus模拟器中运行时无法终止,但注释掉调用free的相关代码后即可正常运行,寻求问题原因及解决办法。
问题原因
Venus模拟器的系统调用规范与你使用的CS61C项目中的实现不匹配:
- 对于
free系统调用(a6=4),Venus要求待释放的内存指针直接放在a0寄存器中作为参数; - 当前的
free实现错误地将a0(指针)移到a1,然后把a0设置为0x3CC,导致系统调用接收到错误的参数,触发未定义行为,最终使程序无法正常终止。
而malloc的实现能正常工作,是因为Venus的malloc系统调用(a6=1)确实要求分配大小放在a1,a0设为0x3CC,这部分符合规范。
解决办法
修改free函数的实现,直接使用a0传递待释放的指针,无需将其移到a1:
free: li a0 0x3CC # 保留系统调用标识 addi a6 x0 4 # free对应的系统调用编号 ecall ret
修改后,调用free时传递的指针会正确被系统调用识别,程序就能正常执行并终止。
内容的提问来源于stack exchange,提问作者denisssj
相关产品推荐
相关产品推荐

