C语言动态字符串数组库存系统的内存异常问题排查
C语言动态库存系统内存访问问题排查与解决
问题现象
- 单次调用
addItemToInventory添加物品,主函数能正常输出内容 - 第二次调用后,主函数中第二个物品显示为
NULL - 第三次及以上调用直接触发段错误
- 函数内部末尾打印新添加的物品内容正常,但返回主函数后对应位置数据丢失
问题根源
核心问题是运算符优先级错误:数组下标运算符[]的优先级高于解引用运算符*。代码中*Inv_content[0]、*Inv_content[*Inv_length]这类写法,实际执行逻辑是先取Inv_content(三级指针)的下标元素再解引用,完全违背了我们的意图——我们需要先解引用Inv_content得到二级指针(库存字符串数组),再访问数组对应下标元素。
这种错误导致malloc分配的字符串地址没有被正确存入库存数组,反而写入了非法内存区域,进而出现主函数数据丢失、越界访问崩溃的现象。
修复方案
将所有错误的*Inv_content[index]写法修改为(*Inv_content)[index],确保先解引用得到库存数组,再操作对应下标元素。修复后的完整代码如下:
修复后的addItemToInventory函数
#include <stdlib.h> #include <stdio.h> #include <string.h> int addItemToInventory(char ***Inv_content,int *Inv_length,char* Item) { int item_name_size=strlen(Item); if (*Inv_length==0) // 库存为空时创建数组 { *Inv_content = malloc(1 * sizeof(char*)); if (*Inv_content) // 数组内存分配成功 { (*Inv_content)[0] = malloc((item_name_size+1) * sizeof(char)); if ((*Inv_content)[0]) // 物品内存分配成功 { strcpy((*Inv_content)[0], Item); *Inv_length += 1; } else // 物品内存分配失败 { printf("无法为物品 '%s' 分配内存(InvContent[0])\n", Item); free(*Inv_content); // 释放已分配的数组内存,避免泄漏 *Inv_content = NULL; return 2; } } else // 数组内存分配失败 { printf("无法为库存分配内存(创建新库存)\n"); return 1; } } else // 库存非空时扩容并添加物品 { char **tmp_pnt; tmp_pnt = realloc(*Inv_content, (*Inv_length+1) * sizeof(char*)); if (tmp_pnt) { *Inv_content = tmp_pnt; (*Inv_content)[*Inv_length] = malloc((item_name_size+1) * sizeof(char)); if ((*Inv_content)[*Inv_length]) { strcpy((*Inv_content)[*Inv_length], Item); *Inv_length += 1; } else // 物品内存分配失败 { printf("无法为物品 '%s' 分配内存(InvContent[%d])\n", Item, *Inv_length); return 2; } } else // 扩容内存分配失败 { printf("无法为库存分配内存(添加物品:realloc)\n"); return 1; } } return 0; }
测试用主函数(含内存释放优化)
int main() { char **Inv_content = NULL; int Inv_length=0; char Item1[12]="Great Sword"; char Item2[8]="Big Bow"; char Item3[10]="Fire Staff"; // 新增测试物品 addItemToInventory(&Inv_content, &Inv_length, Item1); addItemToInventory(&Inv_content, &Inv_length, Item2); addItemToInventory(&Inv_content, &Inv_length, Item3); // 第三次调用测试 printf("\n"); for (int i=0; i<Inv_length;i++) { printf ("物品 %d : %s \n", i+1, Inv_content[i]); } // 释放内存,避免泄漏 for (int i=0; i<Inv_length; i++) { free(Inv_content[i]); } free(Inv_content); return 0; }
验证结果
修复后运行代码,输出如下:
物品 1 : Great Sword 物品 2 : Big Bow 物品 3 : Fire Staff
所有物品正常显示,多次调用不再触发段错误,主函数能正确读取库存数据。
内容的提问来源于stack exchange,提问作者Louis VERAN
相关产品推荐
相关产品推荐

