[英]Segmentation Fault in C programming when using strtok()
I am writing a simple shell and the command (ls & whoami;) works however, when I only type the command ls the code breaks due to a segmentation fault on line 51. I am wonder how to go about this I have used Valgrind and a ton of printf statements but nothing is seeming to work.我正在编写一个简单的 shell 并且命令 (ls & whoami;) 有效,但是当我仅键入命令 ls 时,代码由于第 51 行的分段错误而中断。我想知道如何 go 关于这个我使用了 Valgrind 和大量的 printf 语句,但似乎没有任何效果。 Let me know what you think.
让我知道你的想法。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <wait.h>
#define MAX_LINE 80
#define MAX_CHAR 100
int main()
{
int should_run = 1;
char line[MAX_CHAR];
char *args[MAX_LINE/2 +1];
int ampersandFlag = 0;
/*---------------------------------------------------*/
/* Start of The Program */
while(should_run){
printf("osh>");
fgets(line,MAX_CHAR,stdin);
/* get rid of newline char */
int k = 0;
while(line[k] != '\n'){
k++;
}
line[k] = '\0';
/* get rid of semicolon char */
int l = 0;
while(line[l] != ';'){
l++;
}
line[l] = '\0';
int i = 0;
args[i] = strtok(line, " ");
if(args[i] == NULL){
return 1;
}
while(args[i] != NULL){
printf("%s\n", args[i]);
i++;
args[i] = strtok(NULL, " ");
}
/* Handles the exit command. */
int a = 0;
if(strcmp(args[a], "exit") == 0){
exit(0);
}
if(strcmp(args[1], "&") == 0){
args[1] = NULL;
ampersandFlag = 1;
}
/*---------------------------------------------------*/
/* Start Forking */
int returnForkValue = fork();
int status;
if(returnForkValue < 0){
perror("Fork Failed");
}
else if(returnForkValue == 0){
printf("This is the child\n");
if(ampersandFlag == 1){
int stat;
int retFork = fork();
if(retFork == 0){
printf("This is second child");
execvp(args[2],args);
}
else{
printf("This is the second parent");
waitpid(retFork, &stat, 0);
}
}
execvp(args[0],args);
printf("This won't be printed if execvp is successul\n");
}
else{
printf("This is the parent\n");
waitpid(returnForkValue, &status, 0);
}
}
return 0;
}
If you have exactly one token, only args[0]
will point to a valid string.如果您只有一个标记,则只有
args[0]
将指向一个有效的字符串。 The next args[1]
will be a NULL
pointer.下一个
args[1]
将是NULL
指针。 All other elements of args
will be uninitialized. args
的所有其他元素都将未初始化。
In this case the line在这种情况下,行
if(strcmp(args[1], "&") == 0){
will try to use a NULL
pointer as a string.将尝试使用
NULL
指针作为字符串。
After the loop循环之后
while(args[i] != NULL){
the variable i
will contain the number of tokens.变量
i
将包含令牌的数量。
You should only use index values < i
to access args
.您应该只使用 index values
< i
来访问args
。
The code to execute the second command is wrong.执行第二个命令的代码是错误的。 Instead of
代替
execvp(args[2],args);
you would have to use你必须使用
execvp(args[2],&args[2]);
but this is only valid if the number of tokens is at least 3.但这仅在令牌数至少为 3 时才有效。
BTW: Your code is a bit inconsistent.顺便说一句:您的代码有点不一致。 To check for
"exit"
you use variable a
as index for args
, for other comparisons you use hard-coded numbers.要检查
"exit"
,您使用变量a
作为args
的索引,对于其他比较,您使用硬编码数字。
When I run the program with valgrind
and enter ls
I get an error message showing the NULL
pointer access.当我使用
valgrind
运行程序并输入ls
时,我收到一条错误消息,显示NULL
指针访问。
==30002== Invalid read of size 1
==30002== at 0x483EED4: strcmp (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==30002== by 0x10943A: main (test.c:58)
==30002== Address 0x0 is not stack'd, malloc'd or (recently) free'd
I get an additional error message我收到一条额外的错误消息
==30002== Conditional jump or move depends on uninitialised value(s)
==30002== at 0x10933C: main (test.c:34)
This happens because your loop发生这种情况是因为您的循环
while(line[l] != ';'){
does not check for the terminating NUL
( '\0'
) character and will read past the end of the string if it doesn't contain a semicolon.不检查终止
NUL
( '\0'
) 字符,如果它不包含分号,它将读取字符串的末尾。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.