[英]Segfault while using Strtok() in C
我正在使用C編寫自己的shell並處理流重定向(“>”和“ <”),我正在使用strtok()來獲取它們並存儲相關信息以供以后在程序中使用。 我不確定為什么在撥打第一個電話時會出現segmenation錯誤。 (此刻的代碼非常混亂)。
#include <stdio.h>
#include <stdlib.h>
#include <readline/readline.h>
#include <readline/history.h>
int main (){
char *command, *mypath, *buffer, *arglist[1024], *pathlist[1024],
**ap, *carrotfile1, *carrotfile2;
char* tokenPtr = malloc(1024);
buffer = malloc(1024);
carrotfile1 = malloc(1024);
carrotfile2 = malloc(1024);
int loop = 1, code = 0, fail = 0;
while (loop == 1){
int argnum = 0, pathnum = 0;
mypath = malloc(1024);
if(getenv("MYPATH") == NULL)
strcpy(mypath, "/bin#.");
else
strcpy(mypath, getenv("MYPATH"));
printf("myshell$ ");
command = readline("");
if(strcmp(command, "exit") == 0 || strcmp(command, "quit") == 0)
return 0;
if(strcmp(command, "") == 0)
continue;
/*Tokenizes Command*/
/*
Code 1: > is present
Code 2: < is present
Code 3: Both Present
*/
printf("seg?\n");
tokenPtr = strtok(command, " "); /*Segfaults this line...*/
printf("tokenPtr: %s", tokenPtr);
while(tokenPtr != NULL){
if(strcmp(tokenPtr, ">") == 0){
if(code == 0)
code = 1;
else if(code == 2)
code = 3;
else{
printf("Error: Cannot have multiple equivalent redirects\n");
fail = 1;
}
tokenPtr = strtok(NULL, " ");
strcpy(carrotfile1,tokenPtr);
tokenPtr = strtok(NULL, " ");
strcpy(arglist[argnum], tokenPtr);
argnum++;
}
else if (strcmp(tokenPtr,"<") == 0){
if(code == 0)
code = 2;
else if(code == 1)
code = 3;
else{
printf("Error: Cannot have multiple equivalent redirects\n");
fail = 1;
}
tokenPtr = strtok(NULL, " ");
strcpy(carrotfile2, tokenPtr);
tokenPtr = strtok(NULL, " ");
strcpy(arglist[argnum], tokenPtr);
argnum++;
}
else{
tokenPtr = strtok(NULL, " ");
strcpy(arglist[argnum], tokenPtr);
argnum++;
}
}
}
}
在OS X 10.6.5下測試時,指定的行沒有segfault。 崩潰的地方是:
strcpy(arglist[argnum], tokenPtr);
這是因為arglist
(和pathlist
)被分配了空間,但沒有指向它們的任何字符串。 這是arglist
的示意圖,它是一個指針數組(未初始化為原始代碼,然后初始化為零)和一個數組數組。
當您從arglist
調用未初始化的指針的strcpy
時,您正在復制到一個隨機的內存位置(如第一張圖所示)。
要解決此問題,您應該創建列表類型和對列表進行操作的函數。
typedef struct list {
...
} list_t;
// Initialize a new list. Pass NULL to dynamically allocate list structure.
list_t* createList(list_t* list);
// Destroy a list when done with it. You must free the list* if it was
// dynamically allocated.
void discardList(list_t* list);
// return first item in list
void* first(void);
// return last item in list. Could also be called "top"
void* last(void);
// append item to list
void push(void* item);
// remove & return last item
void* pop(void);
// remove & return first item
void* shift(void);
// prepend item to list
void unshift(void* item);
如果將列表實現為數組,則createList
將使用memset
將arglist
歸零。 在原始代碼中,您還可以在聲明時將{0}
分配給arglist
:
char *arglist[1024] = {0};
如果您只需要在列表中存儲字符串(創建string_list_t
類型)並且不需要某些操作(例如shift
和unshift
),則可以更改API,使用string_list_t
, push
可以為字符串分配空間,復制字符串項並將副本存儲在列表結構中。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.