2014-02-23 21 views
0
#include<stdio.h> 
#include<unistd.h> 
#include<sys/types.h> 
#include<stdlib.h> 
#include<string.h> 
#define MAX_LINE 80 /* Maximum length of command*/ 



struct List 
{ 
char *commandName; 
struct List *next; 
struct List *prev; 
}; 

struct List *head=NULL; 
struct List *curr=NULL; 

void accessList(int); 
void addToList(char *); 
struct List *createNode(char *); 

我想添加歷史記錄功能到我的shell。爲此,我使用結構創建鏈接列表。在我的shell上輸入的命令被分成標記,第一個標記應該存儲在鏈接列表中(雙重).Below是main()函數。使用鏈接列表給出分段錯誤的歷史記錄功能

int main(int argc, char *argv[]) 
{ 
char *args[MAX_LINE/2+1]; /* Command Line Argument*/ 
int should_run=1, status, i, num; 
pid_t pid; 
char str[41], teststr[41]; 
const char delimiter[2]=" "; 
char *token; 
while(should_run) 
{ 
i=0; 
printf("osh>"); 
fflush(stdout); 

fgets(str, sizeof str, stdin);  //reads user input 
str[strlen(str)-1]='\0'; 
token=strtok(str, " "); //breaks them into tokens using the following while loop 

    while(token) 
    { 
     args[i]=strdup(token); 
     printf("args[%d]=%s\n", i, args[i]); 
     i++; 
     token=strtok(NULL, " "); 
    } 
    if(pid<0)   // error in creating child process 
    { 
     printf("\tError in creating child process\n"); 
    }  
    else if(pid==0)  //child process will execute this block 
    { 
     printf("\tChild running it's block\n"); 
     addToList(args[0]);  //store args[0] in Linked List 
     execvp(args[0], args); //args[0] contains name of command 
       exit(1); 
    } 
    else    //parent process will execute this block 
    { 
     pid=wait(&status); 
     printf("\tNow Parent resumes\n"); 

    if(!strcmp(args[0], "exit")) 
    { 
      should_run=0; 
    } 
} 
} 
printf("\tNo. of latest commands you want to view from history=\n"); 
     scanf("%d", &num); 
     accessList(num);   //function to traverse list 
return 0; 
} 
void accessList(int number) 
{ 
int i; 
struct List *temp=(struct List*)malloc(sizeof(struct List)); 
temp=NULL; 
temp=curr; 
for(i=number;i>0;i--) 
{ 
    printf("%d %s", &i, temp->commandName); 
    temp=temp->prev; 
} 
} 
void addToList(char *cmd) 
{ 
struct List *ptrNode=(struct List*)malloc(sizeof(struct List)); 
ptrNode=NULL; 
ptrNode=createNode(cmd); 
if(head->next==NULL) 
{ 
    head->next=ptrNode; 
    ptrNode->prev=head; 
    curr=ptrNode; 
} 
else 
{ 
    curr->next=ptrNode; 
    ptrNode->prev=curr; 
    curr=curr->next; 
} 
} 
struct List *createNode(char *cmd) 
{ 
struct List *node=(struct List*)malloc(sizeof(struct List)); 
node->commandName=cmd; 
node->next=NULL; 
node->prev=NULL; 
return node; 
} 

當我運行這個程序,我的殼工作正常,但要求用戶他們想要從歷史查看最新命令的輸入數字時,它給了我分段錯誤。

+1

有兩件事:第一[不要在C中輸入'malloc'的返回值](http://stackoverflow.com/a/605858/440558)。其次,你在'addToList'中有內存泄漏,你首先調用'malloc'然後覆蓋那個指針*兩次*。 –

+0

至於列表訪問,第一次添加一個節點到列表'head'將是'NULL',所以你在那裏有一個'NULL'指針訪問錯誤。 –

+1

你的代碼中還有更多的內存泄漏。 –

回答

0

你在你的printf() S的一個有一個錯誤:

printf("%d %s", &i, temp->commandName); 

應該是:

printf("%d %s", i, temp->commandName); 

...因爲你需要我的價值,而不是它的地址。

此外,您在fork()之後,在子進程中調用addToList() - 這不會影響父級列表。

您也不會在addToList()中處理head爲NULL的情況(如添加第一項時),因此當您調用它時,您可能會遇到段錯誤。

而且,在你accessList()聲明temp行:

struct List *temp=(struct List*)malloc(sizeof(struct List)); 

...你分配一個結構,你就丟棄(內存泄漏)右後。如果您指向已經存在的節點,則不需要malloc(),如果您剛剛分配一個值,則無需在此處初始化該值 - 但如果您這樣做,則應該初始化它爲NULL。

+0

我使用了上面暗示的所有內容,並嘗試刪除儘可能多的內存泄漏,但現在我收到了錯誤:取消引用指向不完整類型的指針。 – Malhar