我编写了一个程序,它从标准输入中读取命令行,并将其传递给应该将其解析为标记的函数。
这是解析功能:
char** parse_cmdline(char* cmdline) {
char ** arr = malloc(10 * sizeof(char*));
for (int i =0 ; i < 10; ++i)
arr[i] = malloc(30 * sizeof(char));
char * token = strtok(cmdline, " ");
int i = 0;
while(token != NULL) {
if(i > 9) arr = realloc(arr, (i+10)*sizeof(char*) );
arr[i] = token;
token = strtok(NULL, " ");
i++;
}
printf("flag1");
return arr;
}
这就是我使用它的方式main()
:
int main() {
int status;
pid_t pid;
pid = fork();
while(1) {
if(pid < 0) {
status = -1;
perror("Fork");
} else if(pid == 0) {
char* cmd;
printf("$");
if(fgets(cmd, sizeof cmd, stdin) == NULL) break;
parse_cmdline(cmd);
} else {
if( waitpid(pid, &status, 0) != pid ) {
status = -1;
}
break;
}
}
return 0;
}
这是我提供给我的程序的输入示例:
ls l a
预期输出应为:
l
(即第二个参数,由我的解析函数打印)
字面上没有任何反应。甚至不是printf(&#34; flag1&#34;);打印。但是如果我删除char ** commands
并将printf("%s", commands[0]);
放在parse_cmdline函数中,一切都会正常工作,除非我不指定返回。为什么以及如何解决它?
根据要求,这是我的全部代码:
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
char** parse_cmdline(char* cmdline) {
char ** arr = malloc(10 * sizeof(char*));
for (int i =0 ; i < 10; ++i)
arr[i] = malloc(30 * sizeof(char));
char * token = strtok(cmdline, " ");
int i = 0;
while(token != NULL) {
if(i > 9) arr = realloc(arr, (i+10)*sizeof(char*) );
arr[i] = token;
token = strtok(NULL, " ");
i++;
}
printf("%s\n", arr[1]);
return arr;
}
答案 0 :(得分:1)
这部分看起来很奇怪 - 见内联评论:
char ** arr = malloc(10 * sizeof(char*));
for (int i =0 ; i < 10; ++i)
arr[i] = malloc(30 * sizeof(char)); // Here you allocate memory
// for holding a part of the command
char * token = strtok(cmdline, " ");
int i = 0;
while(token != NULL) {
if(i > 9) arr = realloc(arr, (i+10)*sizeof(char*) );
arr[i] = token; // But here you overwrite the pointer value and
// and thereby create a memory leak
token = strtok(NULL, " ");
i++;
}
也许你想要做一个字符串复制 - 比如:
strcpy(arr[i], token); // Instead of arr[i] = token;
此行似乎很奇怪:
if(i > 9) arr = realloc(arr, (i+10)*sizeof(char*) );
您增加arr
以便它可以容纳更多char*
,但这次您不像最初那样为新字符串分配内存。
答案 1 :(得分:0)
首先,您没有为命令分配空间。将cmd
的声明更改为以下内容:
char cmd[100];
不分配内存导致未定义的行为,这(以及正确使用fgets
修复了这一点)。但是你也应该从fgets()
检查100个字符是否足够:
if (strstr(cmd, "\n") == NULL) {
/* the user typed more than 100 characters */
}
因为如果它们还不够,那么你将解析一个不完整的命令行,下次你的循环遍历输入数据时,它将解析更多不完整的命令。
最后,strtok
返回指向 cmd
中的标记的指针,因此您在解析函数开头分配的所有字符数组都是内存泄漏,因为您已更换它们来自循环中strtok
的指针:
arr[i] = token;
/* this throws away the address of the 10-character array you allocated
* at the beginning of the function. You can't free() that memory
* anymore. Your program is "leaking" memory. */
严格地说,顺便说一下,您应该检查realloc
是否返回了有效地址或NULL
。 malloc
也是。在这么小的程序中你不太可能遇到这个问题,但这是正确的做法。
使用后,您还应该处理已解析的命令。您分配了一个包含malloc
和realloc
的指针数组,但您的程序中永远不会free
它们。即使程序很快结束,程序运行时,内存也会泄漏。 (同样,你不太可能会看到一个小程序的问题,但这是一个很好的做法。)