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

给三级指针/数组的数组成员赋值时触发段错误(Segfault)

问题描述

尝试创建结构体指针的二维数组(数组的数组),但在设置第一个数组指针时触发段错误,GDB显示错误发生在palArray[i/4][i%4] = tmpColor;行。提供可编译代码片段,希望找到问题原因或更简单的实现方式,三级指针处理起来很棘手。

错误原因分析
  1. 内存分配完全错误
    原代码中malloc(sizeof(***palArray) * number * colors)逻辑混乱:***palArray是color_t类型,分配的内存仅能存储number*colors个color_t结构体,但color_t***是指向指针数组的指针,需要分层级分配内存——先存调色板指针的外层数组,再为每个调色板存颜色指针的内层数组。
  2. 循环逻辑错误
    • 循环条件i < (number * colors * 3)错误:每个颜色占3字节RGB数据,总循环次数应为number * colors,每次循环处理3字节,而非将总数量乘以3。
    • 索引计算i/4和i%4无依据:应该按调色板索引、颜色索引的层级遍历,而非基于字节索引的除法。
  3. 数组越界风险
    原循环中i+1、i+2会导致paldat越界访问,因为循环终点接近number*colors*3,超出了数组实际长度。
修复方案

方案1:正确分配三级指针内存

按层级分配内存,修正循环逻辑:

color_t*** palettesToColorArray(pSpr_t* sprObj){
    int palette_count = ((sprObj->palnum & 0xF0) >> 4) + 1;
    int colors_per_palette = (sprObj->palnum & 0x0F) + 1;
    // 第一步:分配存储调色板指针的外层数组
    color_t*** palArray = malloc(sizeof(color_t**) * palette_count);
    if(palArray == NULL){
        puts("\n!!> ERR: Memory allocation failure (palettes)");
        exit(1);
    }

    int byte_idx = 0;
    for(int pal = 0; pal < palette_count; pal++){
        // 第二步:为每个调色板分配存储颜色指针的内层数组
        palArray[pal] = malloc(sizeof(color_t*) * colors_per_palette);
        if(palArray[pal] == NULL){
            puts("\n!!> ERR: Memory allocation failure (colors)");
            exit(1);
        }

        for(int col = 0; col < colors_per_palette; col++){
            // 按RGB顺序读取字节,每次移动3位
            color_t* tmpColor = createColorNoAlpha(
                sprObj->paldat[byte_idx],
                sprObj->paldat[byte_idx+1],
                sprObj->paldat[byte_idx+2]
            );
            palArray[pal][col] = tmpColor;
            byte_idx += 3;
        }
    }
    return palArray;
}

注意:释放内存时要逐层释放,避免内存泄漏:

// 释放内存
for(int i = 0; i < palCount; i++){
    for(int j = 0; j < colCount; j++){
        free(colArray[i][j]); // 释放单个color_t对象
    }
    free(colArray[i]); // 释放调色板的颜色指针数组
}
free(colArray); // 释放调色板指针数组

方案2:简化结构,避免三级指针

如果觉得三级指针过于复杂,推荐改用以下两种更易维护的结构:

方式A:二维结构体数组(非指针)

直接分配结构体数组,无需为单个颜色动态分配内存:

color_t** palettesToColorArray(pSpr_t* sprObj){
    int palette_count = ((sprObj->palnum & 0xF0) >> 4) + 1;
    int colors_per_palette = (sprObj->palnum & 0x0F) + 1;
    // 分配外层调色板数组
    color_t** palArray = malloc(sizeof(color_t*) * palette_count);
    if(palArray == NULL){
        puts("\n!!> ERR: Memory allocation failure");
        exit(1);
    }

    int byte_idx = 0;
    for(int pal = 0; pal < palette_count; pal++){
        // 分配内层颜色数组
        palArray[pal] = malloc(sizeof(color_t) * colors_per_palette);
        if(palArray[pal] == NULL){
            puts("\n!!> ERR: Memory allocation failure");
            exit(1);
        }

        for(int col = 0; col < colors_per_palette; col++){
            palArray[pal][col].red = sprObj->paldat[byte_idx];
            palArray[pal][col].grn = sprObj->paldat[byte_idx+1];
            palArray[pal][col].blu = sprObj->paldat[byte_idx+2];
            palArray[pal][col].alp = 255;
            byte_idx +=3;
        }
    }
    return palArray;
}

方式B:一维数组模拟二维结构

用连续内存的一维数组存储所有颜色,通过索引计算模拟二维结构,内存管理最简单:

color_t* palettesToColorArray(pSpr_t* sprObj){
    int palette_count = ((sprObj->palnum & 0xF0) >> 4) + 1;
    int colors_per_palette = (sprObj->palnum & 0x0F) + 1;
    int total_colors = palette_count * colors_per_palette;
    // 分配连续内存存储所有颜色
    color_t* palArray = malloc(sizeof(color_t) * total_colors);
    if(palArray == NULL){
        puts("\n!!> ERR: Memory allocation failure");
        exit(1);
    }

    int byte_idx = 0;
    for(int i = 0; i < total_colors; i++){
        palArray[i].red = sprObj->paldat[byte_idx];
        palArray[i].grn = sprObj->paldat[byte_idx+1];
        palArray[i].blu = sprObj->paldat[byte_idx+2];
        palArray[i].alp = 255;
        byte_idx +=3;
    }
    return palArray;
}

访问时通过palArray[pal_idx * colors_per_palette + col_idx]定位对应颜色即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 02:35:01