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

释放LinesArray时程序无法正常退出的问题排查

释放LinesArray时程序无法正常退出的问题排查

看起来你在实现Crafting Interpreters的行号游程编码时踩了内存操作的坑,程序在调用freeLines时卡住,这大概率是因为之前的数组操作出现了内存越界,破坏了堆的结构,导致后续释放内存时出现异常。咱们一步步拆解问题:

核心问题:数组索引与count变量管理完全混乱

你的设计思路是用[行号, 计数, 行号, 计数,...]的格式存储游程编码,但代码里对count的处理混淆了「已存储元素总数」和「最后一个元素的索引」的概念,直接引发了内存越界:

  1. 初始化阶段的索引错位

    if(array->count == 0){
        array->lines[array->count] = line; // lines[0] = line
        array->count++; // count 变为 1
        array->lines[array->count] = 1; // lines[1] = 1,但count没增加到2
    }
    

    这里明明写入了两个元素,但count只标记为1,后续所有基于count的判断、索引都会彻底错位。

  2. 扩容逻辑判断不足
    当需要添加新的行号条目时,需要占用2个数组位置(行号+计数),但你的扩容判断只检查了capacity < array->count + 1,这会导致需要写入两个元素时,内存空间不够却没有扩容,直接触发数组越界。

  3. 新行号添加时的count操作错误
    遇到新行号时,你两次自增count再写入数据:

    array->count++;
    array->lines[array->count] = line;
    array->count++;
    array->lines[array->count] = 1;
    

    比如count初始是1,执行后count变成3,此时count表示的是最后一个元素的索引,而非已用元素总数,这会让后续的数组访问完全偏离预期,进一步破坏内存。

  4. 内存越界的连锁反应
    上述错误会让你访问超出malloc分配的内存区域,破坏堆的元数据。堆结构损坏后,后续调用free(也就是FREE_ARRAY宏)时,系统无法正确解析堆内存,就会出现程序卡住、崩溃等异常。

修复后的代码示例

咱们重新定义count的含义:让count表示数组中已使用的元素总数,每个游程条目固定占2个元素(行号+计数),这样所有操作都会清晰可控:

#include "lines.h"
#include "memory.h"

void writeLines(LinesArray* array, Line line) {
    // 要添加新条目需要2个位置,提前检查扩容
    if (array->capacity < array->count + 2) {
        int oldCapacity = array->capacity;
        array->capacity = GROW_CAPACITY(oldCapacity);
        array->lines = GROW_ARRAY(Line, array->lines, oldCapacity, array->capacity);
    }

    if (array->count == 0) {
        // 第一个条目:行号在索引0,计数在索引1
        array->lines[0] = line;
        array->lines[1] = 1;
        array->count = 2; // 明确标记已使用2个元素
    } else {
        // 最后一个行号的索引是 count-2,计数是 count-1
        Line lastLine = array->lines[array->count - 2];
        if (lastLine == line) {
            // 计数加1
            array->lines[array->count - 1]++;
        } else {
            // 写入新行号和计数,更新已用元素数
            array->lines[array->count] = line;
            array->lines[array->count + 1] = 1;
            array->count += 2;
        }
    }
}

void freeLines(LinesArray* array) {
    FREE_ARRAY(Line, array->lines, array->capacity);
    initLines(array);
}

额外的小细节

你的lines.c里头文件引用少了闭合双引号:

#include "lines.h  // 修正为 #include "lines.h"
#include "memory.h  // 修正为 #include "memory.h"

这个语法错误会导致编译失败,记得一起改了。

修复这些问题后,数组的内存操作就符合堆的管理规则了,freeLines能正常执行,程序也不会再卡住啦。

备注:内容来源于stack exchange,提问作者user22873067

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.16 02:55:34