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

C语言如何在三级指针中存储数组指针并解决i=4迭代段错误

问题现象

通过gdb定位到程序运行到代码第34行时触发段错误,错误仅在for循环执行最后一次迭代(即i=4)时出现。预期构造的二维数组结构如下:

pegRow[0] = [0]
pegRow[1] = [1, 1]
pegRow[2] = [1, 1, 1]
pegRow[3] = [1, 1, 1, 1]
pegRow[4] = [1, 1, 1, 1, 1]

最初判断故障原因是pegRow分配的内存空间不足,但额外增加内存冗余后错误仍然存在,需要排查定位根因。

原始问题代码
#include <stdio.h>
#include <stdlib.h>

void initializeRows(int*** pegRow);

int main() {
    int **pegRow = malloc(5 * sizeof(int*));

    initializeRows(&pegRow);

    return 0;
}

void initializeRows(int*** pegRow) {
    int i;
    for (i = 0; i < 5; i++) {
        int* pegs = malloc((i + 1) * sizeof(int));
        int j;
        /* First peg is empty */
        if (i == 0) {
            pegs[0] = 0; 
        } else {
            /* The rest of pegs have 1 at entry */
            for (j = 0; j <= i; j++) {
                pegs[j] = 1;
            }
        }
        *pegRow[i] = pegs;
    }
 }
故障根因

段错误的核心原因是C语言运算符优先级导致的内存非法访问,和pegRow的内存分配大小无关:

  • C语言中数组下标运算符[]的优先级高于解引用运算符*,因此代码中*pegRow[i] = pegs;的实际执行逻辑是*(pegRow[i]) = pegs;,而非预期的(*pegRow)[i] = pegs;
  • 传入initializeRows的参数是&pegRow,即指向main函数中pegRow二级指针的三级指针。当i=0时,pegRow[0]刚好对应main中pegRow变量本身,解引用赋值刚好能正确把pegs写入pegRow[0]位置,不会触发错误
  • 当i>0时,pegRow[i]属于越界访问栈内存:程序会把栈上pegRow变量之后的内存值当成合法地址,往对应位置写入pegs指针的值。i=1、2、3时刚好命中栈上可写的未保护区段,不会立刻触发报错;直到i=4时访问到受系统保护的不可写内存段,才会触发段错误,和观察到的“仅最后一次迭代报错”的现象完全吻合。
修复方案

只需要修正赋值语句的运算优先级,给解引用操作增加括号,保证先获取二维数组的基地址,再通过下标写入每行的指针即可:
将原代码第34行的

*pegRow[i] = pegs;

修改为

(*pegRow)[i] = pegs;

修复后代码即可按预期生成目标结构的二维数组,不会再触发段错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 02:39:50