C语言开发命令行界面时结构体数组仅保留最后一轮argv值问题
问题根因
你遇到的问题本质是栈局部变量的生命周期导致的指针悬挂问题,具体原因如下:
- 你在
parse_cmd函数的循环内定义的char* argv[MAX_CMD_SIZE] = {NULL};是栈上的局部数组,它的生命周期仅限当前轮次的循环块,循环每迭代一次,这块内存就会被标记为可复用。 - 你给
newProcess.argv赋值的是这个局部数组的首地址,而非深拷贝数组内的内容。且C语言栈内存分配时,同一块代码块内的局部变量每次都会被分配到相同的栈偏移地址,因此每轮循环的argv数组实际指向同一块内存空间:- 第一轮解析
ls -l时,这块内存填充的是ls、-l、NULL,地址被存入commands[0].argv - 第二轮解析
grep ^a时,同一块内存被覆写为grep、^a、NULL,之前存入commands[0].argv的地址指向的内容同步被修改
- 第一轮解析
- 最终所有
process_t结构体的argv指针都指向同一块栈内存,自然只能读到最后一轮迭代写入的内容。
修复方案
- 方案1:修改
process_t结构体定义,将argv从指针改为定长数组,赋值时直接写入结构体自带的数组空间,无需额外申请内存:
// 结构体定义调整示例 typedef struct process_t { char* path; char* argv[MAX_CMD_SIZE]; // 替换原char** argv的定义 } process_t; // parse_cmd内赋值逻辑调整 process_t newProcess; memset(newProcess.argv, 0, sizeof(newProcess.argv)); int count = 0; for(int argc = position; argc < end; argc++) { newProcess.argv[count] = tokens[argc]; count++; } newProcess.path = tokens[position];
- 方案2:如果必须用指针存储
argv,则改为在堆上申请内存存储参数数组,使用完成后记得手动free避免内存泄漏:
// parse_cmd内替换原有局部argv的定义 char** argv = malloc(sizeof(char*) * MAX_CMD_SIZE); memset(argv, 0, sizeof(char*) * MAX_CMD_SIZE); // 填充参数的逻辑保持不变 newProcess.argv = argv;
内容的提问来源于stack exchange,提问作者Soufyane EL OMARI
相关产品推荐
相关产品推荐

