Monty解释器pop opcode实现BUG求助:存在double free错误
Monty解释器pop opcode调试问题
我已调试超过24小时,仍无法修复Monty解释器中pop opcode的BUG,以下是相关信息:
测试用例(test.m)
push 1 push 2 push 3 pall pop pall pop pall pop pall
实际输出
3 2 1 0 1 free(): double free detected in tcache 2 Aborted (core dumped)
预期输出
3 2 1 2 1 1
当前pop opcode实现代码
#include "monty.h" /** * pop - removes the top element of the stack * @stack: the stack * @line_number: current line number of the bytecode file * * Return: Nothing */ void pop(stack_t **stack, unsigned int line_number) { stack_t *temp = NULL; if (*stack == NULL) { dprintf(2, "L%d: can't pop an empty stack\n", line_number); exit(EXIT_FAILURE); } temp = *stack; *stack = (*stack)->prev; temp->prev = NULL; free(temp); if (*stack) (*stack)->next = NULL; }
问题分析与修复
核心错误
当前pop代码混淆了双向链表的prev和next指针方向:
- 标准Monty栈的实现中,新元素通过
push添加到链表头部作为栈顶,栈顶节点的next指向旧栈顶,prev为NULL。 - 你的代码错误地用
(*stack)->prev更新栈顶指针,导致栈顶被设置为NULL(栈顶节点的prev原本就是NULL),后续pall访问空指针触发未定义行为(输出0),最终引发重复释放错误。
修复后的pop代码
#include "monty.h" /** * pop - removes the top element of the stack * @stack: the stack * @line_number: current line number of the bytecode file * * Return: Nothing */ void pop(stack_t **stack, unsigned int line_number) { stack_t *temp = NULL; if (*stack == NULL) { dprintf(2, "L%d: can't pop an empty stack\n", line_number); exit(EXIT_FAILURE); } temp = *stack; // 用next指针获取下一个栈顶元素(旧栈顶) *stack = (*stack)->next; free(temp); // 若栈不为空,将新栈顶的prev置为NULL(断开与已释放节点的关联) if (*stack) (*stack)->prev = NULL; }
验证说明
修复后:
- 第一次
pop移除栈顶3,栈顶变为2,pall输出2、1; - 第二次
pop移除2,栈顶变为1,pall输出1; - 第三次
pop移除1,栈为空,无额外输出;
完全匹配预期结果,且不会出现重复释放错误。
内容的提问来源于stack exchange,提问作者scisamir
相关产品推荐
相关产品推荐

