为什么我的解析函数 return return 不是所有预期的标记?
Why doesn't my parse function return return all expected tokens?
我编写了一个从标准输入读取命令行的程序,并将其传递给一个函数,该函数应该将其解析为标记。
这是解析函数:
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
(即第二个参数,由我的parse函数打印)
实际上什么也没有发生。甚至 printf("flag1");印刷。但是如果我删除 char ** commands
并将 printf("%s", commands[0]);
放在 parse_cmdline 函数中,一切正常,除了我没有分配 return。为什么以及如何修复它?
根据要求,这是我的全部代码:
#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;
}
首先,您没有为命令分配空间。将 cmd
的声明更改为如下内容:
char cmd[100];
不分配内存会导致未定义的行为,这(以及正确使用 fgets
修复了该问题)。但是你也应该从 fgets()
检查 100 个字符是否足够:
if (strstr(cmd, "\n") == NULL) {
/* the user typed more than 100 characters */
}
因为如果它们还不够,那么您将要解析一个不完整的命令行,并且下一次循环迭代输入数据时,它将解析更多不完整的命令。
最后,strtok
returns 指向标记 in cmd
,所以所有这些字符数组你分配在你的开头parse 函数是内存泄漏,因为你用循环内 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
它们。即使程序很快结束,而程序是 运行,这就是内存泄漏。 (同样,小程序不太可能会出现问题,但这是一种很好的做法。)
这部分看起来很奇怪 - 请参阅内联评论:
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*
但这次你没有像最初那样为新字符串分配内存。
我编写了一个从标准输入读取命令行的程序,并将其传递给一个函数,该函数应该将其解析为标记。
这是解析函数:
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
(即第二个参数,由我的parse函数打印)
实际上什么也没有发生。甚至 printf("flag1");印刷。但是如果我删除 char ** commands
并将 printf("%s", commands[0]);
放在 parse_cmdline 函数中,一切正常,除了我没有分配 return。为什么以及如何修复它?
根据要求,这是我的全部代码:
#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;
}
首先,您没有为命令分配空间。将 cmd
的声明更改为如下内容:
char cmd[100];
不分配内存会导致未定义的行为,这(以及正确使用 fgets
修复了该问题)。但是你也应该从 fgets()
检查 100 个字符是否足够:
if (strstr(cmd, "\n") == NULL) {
/* the user typed more than 100 characters */
}
因为如果它们还不够,那么您将要解析一个不完整的命令行,并且下一次循环迭代输入数据时,它将解析更多不完整的命令。
最后,strtok
returns 指向标记 in cmd
,所以所有这些字符数组你分配在你的开头parse 函数是内存泄漏,因为你用循环内 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
它们。即使程序很快结束,而程序是 运行,这就是内存泄漏。 (同样,小程序不太可能会出现问题,但这是一种很好的做法。)
这部分看起来很奇怪 - 请参阅内联评论:
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*
但这次你没有像最初那样为新字符串分配内存。