C语言动态数组扩容异常求助:分词存储后used值出现随机乱码
问题分析与修复方案
我来帮你拆解一下代码里的核心问题,你的扩容失败和used值变成随机数的情况,主要是两个关键错误导致的:
1. 结构体设计的本质问题
你定义的Array结构体里,pointer是一个固定大小的二维数组char pointer[DEFAULT_SIZE][256]——这种数组的长度是编译时就固定死的,完全没办法通过realloc实现动态扩容。要做能动态增长的字符串数组,必须把pointer改成指向字符串的指针数组(也就是char **pointer;),这样才能在运行时动态调整数组的长度。
2. append函数的内存操作完全错误
你在扩容时的操作完全偏离了目标:
- 你重新
malloc了一个新的Array对象,又对它调用realloc,但我们要扩容的是原数组里的pointer,不是整个Array结构体本身; - 你还重新赋值了函数参数
array,这只会修改函数内部的局部指针,对外部传入的args_list没有任何影响,这直接导致原结构体的内存被非法访问,used字段的值被破坏成随机数。
修正后的完整代码
下面是修复后的代码,我会标注关键修改点:
#include <stdio.h> #include <string.h> #include <stdlib.h> #define DEFAULT_SIZE 3 /* default size of an array of words */ // 修改:把固定二维数组改成指针数组,支持动态扩容 typedef struct { char **pointer; // 指向每个字符串的指针数组 int used; int size; } Array; // 修改:初始化时要为指针数组分配初始内存 void createArray(Array *array, int start_size) { array->used = 0; array->size = start_size; // 为指针数组分配内存,每个元素是一个char*类型的指针 array->pointer = malloc(start_size * sizeof(char*)); if (array->pointer == NULL) { fprintf(stderr, "Failed to allocate initial array memory!\n"); exit(EXIT_FAILURE); } } // 完全重写的append函数,实现正确的动态扩容 void append(Array *array, char* elem) { if (array->used >= array->size) { // 扩容策略:每次把数组大小翻倍(比固定加2更高效) int new_size = array->size * 2; // 重新分配指针数组的内存 char **new_pointer = realloc(array->pointer, new_size * sizeof(char*)); if (new_pointer == NULL) { fprintf(stderr, "Failed to expand array memory!\n"); exit(EXIT_FAILURE); } array->pointer = new_pointer; array->size = new_size; } // 为每个新字符串单独分配内存(要包含字符串结束符'\0'的空间) array->pointer[array->used] = malloc(strlen(elem) + 1); if (array->pointer[array->used] == NULL) { fprintf(stderr, "Failed to allocate memory for string!\n"); exit(EXIT_FAILURE); } strcpy(array->pointer[array->used], elem); array->used++; // 现在这个值会正常递增了 } // 新增:内存释放函数,避免内存泄漏 void freeArray(Array *array) { // 先逐个释放每个字符串的内存 for (int i = 0; i < array->used; i++) { free(array->pointer[i]); } // 再释放指针数组本身的内存 free(array->pointer); // 重置结构体状态 array->pointer = NULL; array->used = 0; array->size = 0; } char *args_str; // passed string Array args_list; // expandable array holding words void parse(char* command) { createArray(&args_list, DEFAULT_SIZE); args_str = strtok(command, " "); while (args_str != NULL) { append(&args_list, args_str); args_str = strtok(NULL, " "); } } // 测试用例 int main() { char test_str[] = "this is a test string with more than three words"; parse(test_str); // 打印结果验证 printf("Parsed %d words:\n", args_list.used); for (int i = 0; i < args_list.used; i++) { printf("%d: %s\n", i+1, args_list.pointer[i]); } // 别忘了释放内存 freeArray(&args_list); return 0; }
额外提醒
- 使用
strtok时要注意:它会直接修改传入的字符串,所以如果传入的是字符串字面量(比如parse("this is test");)会导致未定义行为,一定要传入可修改的字符数组(像测试用例里那样); - 内存分配后一定要检查
malloc/realloc的返回值是否为NULL,避免内存分配失败导致的崩溃; - 不再使用动态数组时,一定要调用
freeArray释放内存,避免内存泄漏。
内容的提问来源于stack exchange,提问作者adamczi
相关产品推荐
相关产品推荐

