如何将字符串复制到不可访问内存?C语言argv赋值问题求助
问题分析与解决
核心问题
你的代码存在两个关键错误:
- 直接
strcpy到未初始化指针:argv是通过malloc(MAXARGS*sizeof(char))分配的指针数组,但数组内的每个argv[argc]都是未初始化的野指针,直接调用strcpy会往随机内存地址写入数据,触发段错误。 - 悬空指针问题:若直接让
argv[argc]=ptr,ptr指向的是buf2内部的内存区域,free(buf2)后该内存被系统回收,argv里的指针就变成悬空指针,后续访问会导致未定义行为。
解决方案
要让argv的内容在buf2释放后依然有效,必须为每个参数独立分配内存,将ptr指向的字符串复制到新内存中,而非直接复用buf2内的指针。
实现方式1:malloc+strcpy手动分配
对每个解析出的参数,先分配足够容纳字符串(含终止符\0)的内存,再复制内容:
while (ptr != NULL) { // 分配内存:字符串长度 + 1(存储'\0') argv[argc] = malloc(strlen(ptr) + 1); if (argv[argc] == NULL) { perror("malloc failed"); exit(1); } strcpy(argv[argc], ptr); argc++; ptr = strtok(NULL, " "); }
实现方式2:用strdup简化代码(POSIX标准)
strdup会自动完成内存分配与字符串复制,等价于malloc+strcpy,代码更简洁:
while (ptr != NULL) { argv[argc] = strdup(ptr); if (argv[argc] == NULL) { perror("strdup failed"); exit(1); } argc++; ptr = strtok(NULL, " "); }
注意内存回收
由于argv的每个元素都单独分配了内存,在eval函数中释放argv前,需要先逐个释放这些元素,避免内存泄漏:
void eval(char* cmdline) { char** argv=malloc(MAXARGS*sizeof(char)); /* Argument list execve() */ char buf[MAXLINE]; /* Holds modified command line */ int bg; /* Should the job run in bg or fg? */ pid_t pid; /* Process id */ strcpy(buf, cmdline); bg = parseline(buf, argv); // 先释放每个参数的内存 int i = 0; while (argv[i] != NULL) { free(argv[i]); i++; } // 再释放指针数组本身 free(argv); }
修改后的完整parseline函数
int parseline(char* buf, char** argv) { int argc; /* Number of args */ int bg; /* Background job? */ char* buf2=malloc(MAXLINE * sizeof(char)); while (*buf && (*buf == ' ')) buf++; buf[strlen(buf) - 1] = ' ';/* Replace trailing '\n' with space */ strcpy(buf2, buf); /* Build the argv list */ argc = 0; char* ptr = strtok(buf2, " "); printf("ptr: %s\n", ptr); while (ptr != NULL) { // 用strdup分配内存并复制字符串 argv[argc] = strdup(ptr); if (argv[argc] == NULL) { perror("strdup error"); exit(EXIT_FAILURE); } argc++; ptr = strtok(NULL, " "); } argv[argc] = NULL; printf("0: %s\n", argv[0]); /* Ignore blank line */ if (argc == 0) return 1; /* Should the job run in the background? */ if ((bg = (*argv[argc - 1] == '&')) != 0) { free(argv[--argc]); // 释放&对应的内存 argv[argc] = NULL; } free(buf2); printf("0: %s\n", argv[0]); if(argv[1]!=NULL) printf("1: %s\n", argv[1]); return bg; }
内容的提问来源于stack exchange,提问作者newb hi
相关产品推荐
相关产品推荐

