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

矩阵加载断言失败求助:mat_load函数magic值匹配断言错误

矩阵保存加载时断言失败问题排查

问题现象

使用mat_save将矩阵保存到文件后,调用mat_load加载时触发断言失败,错误信息如下:

Assertion failed: magic == 0x74616d2e682e6e6e, file ../Headers/nn.h, line 159

相关代码片段

矩阵结构体定义

typedef struct {
    size_t rows;
    size_t cols;
    size_t stride;
    float *es;
} Mat;

矩阵内存分配函数

Mat mat_alloc(size_t rows, size_t cols)
{
    Mat m;
    m.rows = rows;
    m.cols = cols;
    m.stride = cols;
    m.es = NN_MALLOC(sizeof(*m.es)*rows*cols);
    NN_ASSERT(m.es != NULL);
    return m;
}

// 使用示例
Mat t = mat_alloc(img_width*img_height, 3);

注:NN_ASSERT对应标准assert,NN_MALLOC对应标准malloc

矩阵保存函数及调用

const char *out_file_path = "img.txt";
FILE *out = fopen(out_file_path, "w");

mat_save(out, t);

void mat_save(FILE *out, Mat m)
{
    const char *magic = "nn.h.mat";
    fwrite(magic, strlen(magic), 1, out);
    fwrite(&m.rows, sizeof(m.rows), 1, out);
    fwrite(&m.cols, sizeof(m.cols), 1, out);
    for (size_t i = 0; i < m.rows; ++i) {
        size_t n = fwrite(&MAT_AT(m, i, 0), sizeof(*m.es), m.cols, out);
        while (n < m.cols && !ferror(out)) {
            size_t k = fwrite(m.es + n, sizeof(*m.es), m.cols - n, out);
            n += k;
        }
    }
}

#define MAT_AT(m, i, j) (m).es[(i)*(m).stride + (j)]

矩阵加载函数

Mat mat_load(FILE *in)
{
    uint64_t magic;
    fread(&magic, sizeof(magic), 1, in);
    NN_ASSERT(magic == 0x74616d2e682e6e6e);
    size_t rows, cols;
    fread(&rows, sizeof(rows), 1, in);
    fread(&cols, sizeof(cols), 1, in);
    Mat m = mat_alloc(rows, cols);

    size_t n = fread(m.es, sizeof(*m.es), rows*cols, in);
    while (n < rows*cols && !ferror(in)) {
        size_t k = fread(m.es, sizeof(*m.es) + n, rows*cols - n, in);
        n += k;
    }

    return m;
}

问题原因分析

  1. 文件打开模式错误:
    保存时使用"w"文本模式,加载时若使用"r"文本模式,在Windows系统下会自动处理换行符(如\n转\r\n),即使魔数字符串无换行符,文本模式也可能修改字节流,导致读取的魔数与写入值不匹配。

  2. 魔数读写方式不匹配:
    保存时写入ASCII字符串"nn.h.mat",但加载时直接将8字节数据转为uint64_t整数。该方式依赖系统字节序,若系统为大端字节序或文件字节流被修改,就会触发断言失败。

  3. 加载函数读取参数错误:
    mat_load中补全读取的代码参数错误:fread(m.es, sizeof(*m.es) + n, ...)的第二个参数应为单个元素大小sizeof(*m.es),而非sizeof(*m.es)+n,会导致数据加载异常。

  4. 保存函数行数据写入错误:
    mat_save循环内补全写入时,错误地从数组全局第n个元素开始,而非当前行的第n个元素,会导致矩阵数据存储错乱。

解决方法

  1. 使用二进制模式打开文件:
    保存和加载均使用二进制模式,避免文本模式的字节转换:

    // 保存时
    FILE *out = fopen(out_file_path, "wb");
    // 加载时
    FILE *in = fopen(in_file_path, "rb");
    
  2. 统一魔数读写方式:
    直接写入uint64_t类型的魔数值,避免字节序依赖:

    // 修改mat_save的魔数写入部分
    const uint64_t magic = 0x74616d2e682e6e6e;
    fwrite(&magic, sizeof(magic), 1, out);
    
  3. 修复加载函数的读取参数:
    将补全读取的代码修改为:

    size_t k = fread(m.es + n, sizeof(*m.es), rows*cols - n, in);
    
  4. 修复保存函数的行数据写入逻辑:
    补全写入时从当前行的未写入位置开始:

    size_t k = fwrite(&MAT_AT(m, i, n), sizeof(*m.es), m.cols - n, out);
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 03:58:14