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

C语言char**指针malloc/realloc内存分配异常问题求助

问题描述

我为测试char**类型的malloc与realloc操作,编写了简化代码:将字符串"debugging_in_progress"通过独立malloc的指针(非浅拷贝)存储到char**类型的texts数组中,初始数组大小为10,经两次扩容后变为40,需存储35个字符串。调试时发现以下问题:

  • 程序输出丢失了前2个字符串的指针;
  • 存储完所有指针后,使用%s打印字符串会触发Segmentation Fault(段错误),即使避开疑似丢失的指针也无法解决;
  • 若将texts初始分配大小设为4,程序会直接崩溃。

测试代码

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
void reallocMem(char **currArray, int* maxSize, int currSize);
void memCheck(void ptr);

int main()
{
char debug[100] = "debugging_in_progress";

    int length = strlen(debug);
    char** texts = (char**) malloc (sizeof(char*) * 10);
    int max = 10;
    int c;
    
    for (int i= 0; i < 35; ++i)
    {
        reallocMem(texts,&max,i);
        texts[i] = (char*) malloc (sizeof(char) * length);
        printf("OG %d.: %p\n",i,texts[i]);
        
        for (int j = 0; j <= length; j++)
        {
            texts[i][j] = debug[j];
        }
        printf("OG %d.TEXT: %s\n",i,texts[i]);
        c++;
    
    }
    
    for (int i = 10; i < 35; ++i)
    {
        printf("%d.:%p\n",i+1,texts[i]);
        // free(texts[i]);
    }
    printf("%d/%d",c,max);
    return 0;

}

void reallocMem(char **currArray, int* maxSize, int currSize)
{
if (currSize >= (*maxSize))
{
(*maxSize) *= 2;
currArray = (char*) realloc(currArray, (*maxSize) * sizeof(char*));
memCheck(currArray);

    }

}

void memCheck(void* ptr)
{
if (!ptr)
{
fprintf(stderr,"Row couldn't be processed: no memory left");
exit(7);
}
}

程序输出

▒'}@(}▒&}▒%}▒(})}<code>(} (}▒&}'} &}▒(}▒(} '}@&}&}</code>'} )}▒%}ugging_in_progress

OG 3.: 00000208e97d23c0
OG 3.TEXT: debugging_in_progress

OG 4.: 00000208e97d23e0
OG 4.TEXT: debugging_in_progress

OG 5.: 00000208e97d2400
OG 5.TEXT: debugging_in_progress

OG 6.: 00000208e97d2420
OG 6.TEXT: debugging_in_progress

OG 7.: 00000208e97d2440
OG 7.TEXT: debugging_in_progress

OG 8.: 00000208e97d2460
OG 8.TEXT: debugging_in_progress

OG 9.: 00000208e97d2480
OG 9.TEXT: debugging_in_progress

OG 10.: 00000208e97d12f0
OG 10.TEXT: debugging_in_progress

OG 11.: 00000208e97d1310
OG 11.TEXT: debugging_in_progress

OG 12.: 00000208e97d1330
OG 12.TEXT: debugging_in_progress

OG 13.: 00000208e97d2550
OG 13.TEXT: debugging_in_progress

OG 14.: 00000208e97d28a0
OG 14.TEXT: debugging_in_progress

OG 15.: 00000208e97d2940
OG 15.TEXT: debugging_in_progress

OG 16.: 00000208e97d27c0
OG 16.TEXT: debugging_in_progress

OG 17.: 00000208e97d2840
OG 17.TEXT: debugging_in_progress

OG 18.: 00000208e97d26c0
OG 18.TEXT: debugging_in_progress

OG 19.: 00000208e97d25e0
OG 19.TEXT: debugging_in_progress

OG 20.: 00000208e97d2880
OG 20.TEXT: debugging_in_progress

OG 21.: 00000208e97d2900
OG 21.TEXT: debugging_in_progress

OG 22.: 00000208e97d2860
OG 22.TEXT: debugging_in_progress

OG 23.: 00000208e97d2820
OG 23.TEXT: debugging_in_progress

OG 24.: 00000208e97d2680
OG 24.TEXT: debugging_in_progress

OG 25.: 00000208e97d2700
OG 25.TEXT: debugging_in_progress

OG 26.: 00000208e97d2620
OG 26.TEXT: debugging_in_progress

OG 27.: 00000208e97d28c0
OG 27.TEXT: debugging_in_progress

OG 28.: 00000208e97d28e0
OG 28.TEXT: debugging_in_progress

OG 29.: 00000208e97d2720
OG 29.TEXT: debugging_in_progress

OG 30.: 00000208e97d2640
OG 30.TEXT: debugging_in_progress

OG 31.: 00000208e97d2600
OG 31.TEXT: debugging_in_progress

OG 32.: 00000208e97d2760
OG 32.TEXT: debugging_in_progress

OG 33.: 00000208e97d2920
OG 33.TEXT: debugging_in_progress

OG 34.: 00000208e97d25c0
OG 34.TEXT: debugging_in_progress

11.:0000007373657267
12.:00000208e97d1310 13.:00000208e97d1330
14.:00000208e97d2550
15.:00000208e97d28a0
16.:00000208e97d2940
17.:00000208e97d27c0
18.:00000208e97d2840
19.:00000208e97d26c0
20.:00000208e97d25e0
21.:00000208e97d2880
22.:00000208e97d2900
23.:00000208e97d2860
24.:00000208e97d2820
25.:00000208e97d2680
26.:00000208e97d2700
27.:00000208e97d2620
28.:00000208e97d28c0
29.:00000208e97d28e0
30.:00000208e97d2720
31.:00000208e97d2640
32.:00000208e97d2600
33.:00000208e97d2760
34.:00000208e97d2920
35.:00000208e97d25c0
35/40
问题分析与修复

核心错误点

  1. reallocMem参数传递错误:
    函数接收的char **currArray是值传递,realloc后修改的是局部指针,主函数的texts指针不会更新。当realloc返回新地址时,主函数仍使用旧的失效指针,导致非法内存访问,这是崩溃和指针丢失的根本原因。
  2. 字符串内存分配不足:
    strlen(debug)返回不含终止符\0的长度,但malloc只分配了对应字符的空间,未给\0留位置。后续复制时j <= length会越界写入,破坏内存结构引发段错误。
  3. 未初始化变量c:
    int c;未初始化就执行c++,属于未定义行为。
  4. realloc类型转换错误:
    强制转换为char*,但实际需要char**,类型不匹配导致指针操作错误。
  5. 扩容时机错误:
    判断条件currSize >= (*maxSize)会导致越界访问后才扩容,此时已触发非法内存操作。

修复后的完整代码

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

void reallocMem(char ***currArray, int* maxSize, int currSize);
void memCheck(void* ptr);

int main()
{
    char debug[100] = "debugging_in_progress";
    int length = strlen(debug);
    char** texts = (char**)malloc(sizeof(char*) * 10);
    int max = 10;
    int c = 0; // 初始化变量
    
    for (int i = 0; i < 35; ++i)
    {
        reallocMem(&texts, &max, i);
        // 分配内存时多留一个字节存终止符
        texts[i] = (char*)malloc(sizeof(char) * (length + 1));
        memCheck(texts[i]);
        
        printf("OG %d.: %p\n", i, texts[i]);
        strcpy(texts[i], debug); // 替代手动复制,更简洁安全
        printf("OG %d.TEXT: %s\n", i, texts[i]);
        c++;
    }
    
    for (int i = 0; i < 35; ++i)
    {
        printf("%d.:%p -> %s\n", i+1, texts[i], texts[i]);
        free(texts[i]); // 释放每个字符串的内存
    }
    free(texts); // 释放指针数组的内存
    printf("%d/%d\n", c, max);
    return 0;
}

void reallocMem(char ***currArray, int* maxSize, int currSize)
{
    // 当前元素数量等于最大容量时扩容,避免越界
    if (currSize == *maxSize)
    {
        *maxSize *= 2;
        // 正确转换为char**类型
        *currArray = (char**)realloc(*currArray, *maxSize * sizeof(char*));
        memCheck(*currArray);
    }
}

void memCheck(void* ptr)
{
    if (!ptr)
    {
        fprintf(stderr, "Row couldn't be processed: no memory left");
        exit(7);
    }
}

修复说明

  • 调整reallocMem参数为char ***currArray,确保能修改主函数中texts指针的指向,扩容后使用新的有效地址。
  • 字符串内存分配增加1个字节,保证能存储终止符\0,避免越界写入。
  • 初始化变量c,消除未定义行为。
  • 修正realloc的类型转换,确保类型匹配。
  • 调整扩容时机,在当前元素数量等于最大容量时就扩容,避免越界访问。
  • 添加内存释放代码,避免内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 03:55:22