C 段错误!

发布于 2024-09-03 13:48:51 字数 4781 浏览 6 评论 0原文

这至少对我来说很奇怪......程序运行正常。但是在我第四次调用 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;
    }
}

更新: SegFault 仅当进入 InsertSort() 函数的“else”循环时才会出现。 我观察到,当我尝试添加后面的列表名称时,会出现分段错误。 例如,如果列表中存在:

[姓名:b 姓氏:b 金额:6 描述:b] [姓名:c 姓氏:c 金额:5 描述:c] [姓名:d 姓氏:d 数量:4 描述:d] [姓名:e 姓氏:e 金额:3 描述:e] [姓名:g 姓氏:g 数量:2 描述:g] [姓名:x 姓氏:x 金额:1 描述:x]

我输入:“xz 77 gege”有一个分段 但如果我输入“xa 77 gege”,它会正常继续......

It seems at least weird to me... The program runs normally.But after I call the enter() function for the 4th time,there is a segmentation fault!I would appreciate any help.

With the following function enter() I wanna add user commands' datas to a list.

[Some part of the code is already posted on another question of me, but I think I should post it again...as it's a different problem I'm facing now.]

    /* 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 appears only when it gets on the 'else' loop of InsertSort() function.
I observed that segmentation fault appears when i try to put on the list names that are after it.
For example, if in the list exists:

[Name:b Surname:b Amount:6 Description:b]
[Name:c Surname:c Amount:5 Description:c]
[Name:d Surname:d Amount:4 Description:d]
[Name:e Surname:e Amount:3 Description:e]
[Name:g Surname:g Amount:2 Description:g]
[Name:x Surname:x Amount:1 Description:x]

and i put: " x z 77 gege" there is a segmentation
but if i put "x a 77 gege" it continues normally....

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

身边 2024-09-10 13:48:51

无法发表评论,所以这里是:

  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!)
  }

换句话说,如果您的程序找到任何满足循环内条件并设置“第二”的条目,它将崩溃。 (这会触发列表“内部”的预期添加)。

好的〜没有时间等待答案:o),如果您想在“第二个”之后输入,请将代码更改为:

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

解释(S 是“第二个”,N 是“newNode”,AB 只是一些现有条目在列表中):

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

Can't post into comment, so here it goes:

  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!)
  }

In other words, your program will crash if it finds any entry that satisfy conditions inside the loop and set 'second'. (This triggers intended addition "inside" the list).

Ok ~ no time to wait for answer :o), in a case you want to enter "after" the 'second' change code to this:

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

explanation (S is 'second', N a 'newNode', A B just some exisiting entries in the list):

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
一身软味 2024-09-10 13:48:51

不确定是什么导致了这个错误,但我确实看到了这个错误的模式:

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

sizeof(short_name) 将始终是相同的东西(通常 32 位平台为 4,64 位平台为 8),所以不是此处使用的正确值。你应该这样做:

strncpy(short_name, curToken, strlen(curToken) + 1);

Not sure what's causing the bug, but I did see this bad pattern:

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

sizeof(short_name) will be always the same thing (usually 4 for 32 bit platforms and 8 for 64 bit platforms) so is not the correct value to use here. You should be doing:

strncpy(short_name, curToken, strlen(curToken) + 1);
素食主义者 2024-09-10 13:48:51

使用诸如 valgrind 之类的东西来查找此类问题。

Use something like valgrind to find problems like this.

那小子欠揍 2024-09-10 13:48:51

退出 while 循环需要首先为空。在 else 语句中,您首先尝试访问。

Falling out of your while loop requires first to be null. In the else statement you attempt to access first.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文