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

C语言函数内动态分配二维数组后外部访问段错误问题分析

动态分配二维数组时传参导致段错误的原因与解决方法

问题描述

想在独立函数中为char类型二维数组(字符串数组)动态分配内存,主函数定义双指针res并传入alloc_arr函数,函数内用malloc完成内存分配并写入字符串,但退出函数后主函数访问res时出现段错误。原本以为主函数的res指针在函数结束后仍可使用,malloc返回的动态内存地址能正常访问,可只有让函数直接返回指针程序才能正常运行,int类型二维数组也遇到同样问题。需要明确第一种方式失效的原因,以及修复方法。

错误代码示例

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int alloc_arr(char **res)
{
    size_t i;

    res = (char **)malloc(200 * sizeof(char *));
    if (res == NULL)
        return 0;
    i = 0;
    while (i < 200)
    {
        res[i] = (char *)malloc(100 * sizeof(char));
        if (res[i] == NULL)
            return 0;
        i++;
    }
    strncpy(&res[0][0], "string", 100);
    printf("res[0] = %s\n", res[0]);
    return 1;
}

void free_arr(char **res)
{
    int i = 0;
    for (; i < 200; i++)
        free(res[i]);
    free(res);
}

int main(void)
{
    char **res;
    res = NULL;
    if (alloc_arr(res))
        printf("res[0] = %s\n", res[0]); /* 此处触发段错误 */
    else
        return 1;
    free(res);
    return 0;
}

可行的返回指针方式示例

int **alloc_int(int **res)
{
    size_t i;

    res = (int **)malloc(20 * sizeof(int *));
    if (res == NULL)
        return NULL;
    i = 0;
    while (i < 20)
    {
        res[i] = (int *)malloc(10 * sizeof(int));
        if (res[i] == NULL)
            return NULL;
        i++;
    }
    res[0][0] = 10;
    printf("res[0] = %d\n", res[0][0]);
    return res;
}

void free_int(int **res)
{
    int i = 0;
    for (; i < 20; i++)
        free(res[i]);
    free(res);
}

int main(void)
{
    int **res;
    res = NULL;
    if ((res = alloc_int(res)) != NULL)
        printf("res[0] = %d\n", res[0][0]);
    else
        return 1;
    free(res);
    return 0;
}

失效原因

  • C语言的函数参数传递是值传递:当把char **res传入alloc_arr时,函数会创建一个res的副本。函数内给这个副本赋值malloc返回的地址,修改的只是副本,主函数里的原始res指针始终是NULL。主函数访问res[0]本质是访问NULL指针指向的内存,直接触发段错误。
  • 返回指针的方式能正常运行,是因为函数把分配好的内存地址返回给了主函数的res,让原始指针指向了正确的动态内存区域。

修复方法

要修改主函数中的原始指针,需要传递指针的指针(即char ***res),通过三级指针间接修改主函数里的二级指针值。

修正后的代码

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int alloc_arr(char ***res)
{
    size_t i;
    // 解引用三级指针,修改主函数中的原始二级指针
    *res = (char **)malloc(200 * sizeof(char *));
    if (*res == NULL)
        return 0;
    i = 0;
    while (i < 200)
    {
        (*res)[i] = (char *)malloc(100 * sizeof(char));
        if ((*res)[i] == NULL)
            return 0;
        i++;
    }
    strncpy((*res)[0], "string", 100);
    printf("res[0] = %s\n", (*res)[0]);
    return 1;
}

void free_arr(char **res)
{
    int i = 0;
    for (; i < 200; i++)
        free(res[i]);
    free(res);
}

int main(void)
{
    char **res;
    res = NULL;
    // 传入res的地址,传递三级指针
    if (alloc_arr(&res))
        printf("res[0] = %s\n", res[0]);
    else
        return 1;
    free_arr(res);
    return 0;
}

关键修改点

  1. 函数参数从char **res改为char ***res,接收主函数中二级指针的地址。
  2. 函数内通过*res访问并修改主函数的原始二级指针,让它指向malloc分配的内存。
  3. 主函数调用alloc_arr时传入&res,传递二级指针的地址。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 09:01:33