C-Ошибка сегментации! - PullRequest
1 голос
/ 25 мая 2010

Мне это кажется по меньшей мере странным ... Программа работает нормально. Но после того, как я в четвертый раз вызываю функцию enter (), возникает ошибка сегментации! Буду признателен за любую помощь.

С помощью следующей функции enter () я хочу добавить данные пользовательских команд в список.

[Некоторая часть кода уже опубликована по другому моему вопросу, но я думаю, что я должен опубликовать его снова ... так как сейчас я столкнулся с другой проблемой.]

    /* struct for all the datas that user enters on file*/
typedef struct catalog    
{      char short_name[50];                    
       char surname[50];                       
       signed int amount;                      
       char description[1000];              
       struct catalog *next;
}catalog,*catalogPointer;   

catalogPointer current;
catalogPointer head = NULL; 

void enter(void)    //user command: i <name> <surname> <amount> <description>

{   
    int n,j=2,k=0;
    char temp[1500];
    char *short_name,*surname,*description;
    signed int amount;

    char* params = strchr(command,' ') + 1;  //strchr returns a pointer to the 1st space on the command.U want a pointer to the char right after that space.
    strcpy(temp, params);               //params is saved as temp.

    char *curToken = strtok(temp," ");      //strtok cuts 'temp' into strings between the spaces and saves them to 'curToken'
    printf("temp is:%s \n",temp);

    printf("\nWhat you entered for saving:\n");

    for (n = 0; curToken; ++n)          //until curToken ends:
    {   
        if (curToken)
        {   short_name = malloc(strlen(curToken) + 1);
            strncpy(short_name, curToken, sizeof (short_name));     
        }   
        printf("Short Name: %s \n",short_name);             

        curToken = strtok(NULL," ");                    
        if (curToken)
        {   surname = malloc(strlen(curToken) + 1);
            strncpy(surname, curToken,sizeof (surname));    }   
        printf("SurName: %s \n",surname);

        curToken = strtok(NULL," ");                    
        if (curToken)
        {   //int * amount= malloc(sizeof (signed int *));
            char *chk;                      
            amount = (int) strtol(curToken, &chk, 10);      

            if (!isspace(*chk) && *chk != 0)            
                    fprintf(stderr,"Warning: expected integer value for amount, received %s instead\n",curToken);
        }
        printf("Amount: %d \n",amount);
        curToken = strtok(NULL,"\0");                   
        if (curToken)
        {   description = malloc(strlen(curToken) + 1);
            strncpy(description, curToken, sizeof (description));   
        }
        printf("Description: %s \n",description);
        break;
    }

    if (findEntryExists(head, surname,short_name) != NULL)              //call function in order to see if entry exists already on the catalog
        printf("\nAn entry for <%s %s> is already in the catalog!\nNew entry not entered.\n",short_name,surname);
    else
    {
        printf("\nTry to entry <%s %s %d %s> in the catalog list!\n",short_name,surname,amount,description);
        newEntry(&head,short_name,surname,amount,description);  
        printf("\n**Entry done!**\n");
    }
    // Maintain the list in alphabetical order by surname.


}

catalogPointer findEntryExists (catalogPointer head, char num[],char first[])
{   catalogPointer p = head;
    while (p != NULL && strcmp(p->surname, num) != 0 && strcmp(p->short_name,first) != 0)      
    {   p = p->next;    }
    return p;
}

catalogPointer newEntry (catalog** headRef,char short_name[], char surname[], signed int amount, char description[])
{   
    catalogPointer newNode = (catalogPointer)malloc(sizeof(catalog));
    catalogPointer first;
    catalogPointer second;
    catalogPointer tmp;
    first=head;
    second=NULL;

    strcpy(newNode->short_name, short_name);        
    strcpy(newNode->surname, surname);
    newNode->amount=amount;
    strcpy(newNode->description, description);

    while (first!=NULL)                     
    {       if (strcmp(surname,first->surname)>0)
            second=first;
        else if (strcmp(surname,first->surname)==0)
            {
               if (strcmp(short_name,first->short_name)>0)
                   second=first;
            }
        first=first->next;
    }
    if (second==NULL)
    {       newNode->next=head;
        head=newNode;
    }
    else                             //SEGMENTATION APPEARS WHEN IT GETS HERE!
    {       tmp=second->next;
            newNode->next=tmp;
            first->next=newNode;
    }
}

UPDATE: SegFault появляется только тогда, когда он входит в цикл 'else' функции InsertSort (). Я заметил, что ошибка сегментации появляется, когда я пытаюсь добавить в список имена, следующие за ним. Например, если в списке существует:

[Имя: b Фамилия: b Сумма: 6 Описание: b] [Имя: c Фамилия: c Количество: 5 Описание: c] [Имя: d Фамилия: d Количество: 4 Описание: d] [Имя: e Фамилия: e Количество: 3 Описание: e] [Имя: г Фамилия: г Количество: 2 Описание: г] [Имя: x Фамилия: x Сумма: 1 Описание: x]

и я поставил: "x z 77 gege" есть сегментация но если я поставлю "x a 77 gege", он продолжится нормально ....

Ответы [ 4 ]

4 голосов
/ 25 мая 2010

Не может публиковать в комментариях, вот оно:

  while (first!=NULL)  {  //-> this loop can exit ONLY with 'first' being NULL
    if (strcmp(surname,first->surname)>0)
      second=first;
    else if (strcmp(surname,first->surname)==0)  {
      if (strcmp(short_name,first->short_name)>0)
        second=first;
    }
    first=first->next;
  } 
  if (second==NULL) {       
    newNode->next=head;
    head=newNode;
  }
  else { 
    tmp=second->next;
    newNode->next=tmp;
    first->next=newNode; // first used (but it's NULL!)
  }

Другими словами, ваша программа потерпит крах, если найдет какую-либо запись, которая удовлетворяет условиям внутри цикла, и установит «second». (Это вызывает намеренное добавление «внутри» списка).

Ладно ~ нет времени ждать ответа: о), в случае, если вы хотите ввести «после» второго кода, измените его на:

  if (second==NULL) {       
    newNode->next=head;
    head=newNode;
  }
  else { 
    newNode->next=second->next;
    second->next=newNode; 
  }

объяснение (S - «второй», N - «новый узел», A B - только некоторые существующие записи в списке):

initial:
       N

  A -> S -> B

first assignment:
       N ---\
            |
            v
  A -> S -> B

second assignment:

       N ---\
       ^    |
       |    v
  A -> S    B

and thus:
  A-> S -> N -> B
4 голосов
/ 25 мая 2010

Не уверен, что является причиной ошибки, но я видел этот плохой шаблон:

char *short_name;
short_name = malloc(strlen(curToken) + 1);
strncpy(short_name, curToken, sizeof (short_name));  

sizeof(short_name) всегда будет одним и тем же (обычно 4 для 32-битных платформ и 8 для 64-битных платформ), поэтому здесь не правильное значение. Вы должны делать:

strncpy(short_name, curToken, strlen(curToken) + 1);
1 голос
/ 25 мая 2010

Используйте что-то вроде valgrind , чтобы найти подобные проблемы.

0 голосов
/ 25 мая 2010

Выпадение из цикла while требует, чтобы сначала было нулевым. В операторе else вы пытаетесь получить доступ первым.

...