使用链接列表提供分段错误的历史记录功能

时间:2014-02-23 19:38:45

标签: c

#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;
}

当我运行这个程序时,我的shell运行正常但是当要求用户输入他们想要从历史记录中查看的最新命令的数量时,它会给我分段错误。

1 个答案:

答案 0 :(得分:0)

您的某个printf() s:

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

应该是:

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

...因为你需要i的值,而不是它的地址。

此外,您在子进程中addToList()之后调用fork() - 这不会影响父级中的列表。

你也没有处理headaddToList()为空(如添加第一项)时的情况,所以当你打电话给它时,你可能会得到一个段错误。

另外,在temp中声明accessList()的行:

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

...你分配一个结构,然后你随后丢弃(内存泄漏)。如果您指向已经存在的节点,则不需要malloc(),如果您在此之后立即分配值,则不需要在此处初始化值 - 但如果你这样做,你应该把它初始化为NULL。