linkedList - 分段错误(核心转储)

时间:2016-04-08 14:00:00

标签: c linked-list segmentation-fault

在我将“ListRemoveHead”功能添加到我的链接列表代码后,我经常遇到分段错误...

如果我注释掉ListRemoveHead函数,代码运行良好, 它也似乎我在主要的出口处得到了分段错误...

你可以帮我找一下这个bug ......

*更新了 - gdb输出,仍然是分段错误。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

typedef struct Person Person;

struct Person
{
    int     m_id;         /* Primary Key */
    char    m_name[128];
    int     m_age;
    Person* m_next;
};



/* create a person and give values */
Person* CreatePerson(int _id,char* _name,int _age)
{
    Person* ptrPerson;

    ptrPerson=malloc(sizeof(Person));

    ptrPerson->m_id = _id;
    strcpy(ptrPerson->m_name , _name);
    ptrPerson->m_age = _age;
    ptrPerson->m_next = NULL; 

    return ptrPerson;
}

/* insert a person to the top of the list */
Person* ListInsertHead(Person* _head ,Person* _p)
{
    if(NULL == _head)
    {
        return _p;
    }

    _p->m_next = _head;
    _head = _p;

    return _head;

}

Person* ListRemoveHead(Person* _head, Person** _item)
{
    if(NULL == _head)
    {
        return NULL;
    }

    *_item = _head;
    _head = _head->m_next;

    return _head;
}



void PrintList(Person* _head)
{
    if(NULL == _head)
    {
        return;
    }


    while(NULL != _head->m_next)
    {

        printf("id number %d, name is %s, age is %d\n", _head->m_id,_head->m_name,_head-> m_age);
        _head = _head->m_next;
        if(NULL == _head->m_next)
        {
            break;
        }
    }


}



int main()
{


    Person* ptrPerson[3];
    Person* ptrHead;
    Person** pptrItem ;

    ptrHead = malloc(sizeof(Person));

    ptrPerson[0] = CreatePerson(1,"mishel",4);
    ptrPerson[1] = CreatePerson(2,"peter",29);
    ptrPerson[2] = CreatePerson(3,"alex",32);



    ptrHead = ListInsertHead(ptrHead ,ptrPerson[0]);
    ptrHead =  ListInsertHead(ptrHead ,ptrPerson[1]);
    ptrHead = ListInsertHead(ptrHead ,ptrPerson[2]);


    ptrHead=ListRemoveHead(ptrHead,pptrItem);

    PrintList(ptrHead);
/*  printf("the removed item is:%d\n", (**pptrItem).m_id);*/

    return 0;
}

启动程序:/home/peter/Desktop/a.out

Breakpoint 1, CreatePerson (_id=1, _name=0x8048725 "mishel", _age=4)
    at linkedList.c:22
22      ptrPerson=malloc(sizeof(Person));
(gdb) n
24      ptrPerson->m_id = _id;
(gdb) n
25      strcpy(ptrPerson->m_name , _name);
(gdb) n
26      ptrPerson->m_age = _age;
(gdb) n
27      ptrPerson->m_next = NULL; 
(gdb) n
29      return ptrPerson;
(gdb) n
30  }
(gdb) n
main () at linkedList.c:97
97      ptrPerson[1] = CreatePerson(2,"peter",29);
(gdb) n

Breakpoint 1, CreatePerson (_id=2, _name=0x804872c "peter", _age=29)
    at linkedList.c:22
22      ptrPerson=malloc(sizeof(Person));
(gdb) 
24      ptrPerson->m_id = _id;
(gdb) 
25      strcpy(ptrPerson->m_name , _name);
(gdb) 
26      ptrPerson->m_age = _age;
(gdb) 
27      ptrPerson->m_next = NULL; 
(gdb) 
29      return ptrPerson;
(gdb) 
30  }
(gdb) 
main () at linkedList.c:98
98      ptrPerson[2] = CreatePerson(3,"alex",32);
(gdb) 

Breakpoint 1, CreatePerson (_id=3, _name=0x8048732 "alex", _age=32)
    at linkedList.c:22
22      ptrPerson=malloc(sizeof(Person));
(gdb) 
24      ptrPerson->m_id = _id;
(gdb) 
25      strcpy(ptrPerson->m_name , _name);
(gdb) 
26      ptrPerson->m_age = _age;
(gdb) 
27      ptrPerson->m_next = NULL; 
(gdb) 
29      return ptrPerson;
(gdb) 
30  }
(gdb) 
main () at linkedList.c:102
102     ptrHead = ListInsertHead(ptrHead ,ptrPerson[0]);
(gdb) 
103     ptrHead =  ListInsertHead(ptrHead ,ptrPerson[1]);
(gdb) 
104     ptrHead = ListInsertHead(ptrHead ,ptrPerson[2]);
(gdb) 
107     ptrHead=ListRemoveHead(ptrHead,pptrItem);
(gdb) 
109     PrintList(ptrHead);
(gdb) 
id number 2, name is peter, age is 29
id number 1, name is mishel, age is 4
112     return 0;
(gdb) 
113 }
(gdb) 
__libc_start_main (main=0x8048581 <main>, argc=1, argv=0xbffff0d4, 
    init=0x8048670 <__libc_csu_init>, fini=0x80486e0 <__libc_csu_fini>, 
    rtld_fini=0xb7fed180 <_dl_fini>, stack_end=0xbffff0cc) at libc-start.c:321
321 libc-start.c: No such file or directory.
(gdb) 


Program received signal SIGSEGV, Segmentation fault.
__run_exit_handlers (status=status@entry=0, listp=0xb7fbf3c4 <__exit_funcs>, run_list_atexit=run_list_atexit@entry=true) at exit.c:54
54  exit.c: No such file or directory.
(gdb) 






Program terminated with signal SIGSEGV, Segmentation fault.
The program no longer exists.

2 个答案:

答案 0 :(得分:0)

看起来你需要在 ListRemoveHead 函数中交换这一行:

*_item = _head;
_head = _head->m_next;

因为您使用 _item 返回无效指针(已释放)。

实际上,后来我注意到你要打印删除的项目ID。然后,您应该重新设计代码,而不是只返回id:

Person* ListRemoveHead(Person* _head, int* _item)
{
   ...
   *_item = _head->m_id;
   _head = _head->m_next;

只是不要忘记检查主代码中的返回值:

ptrHead=ListRemoveHead(ptrHead, &item);
if (ptrHead) {
   PrintList(ptrHead);
   printf("the removed item is:%d\n", item);
} else {
   printf("list is empty\n")
}

<强>更新

您还可以访问未初始化的内存,因为您拥有主要

 ptrHead = malloc(sizeof(Person));

永远不会被初始化并成为列表的末尾。所以,实际上你不需要这一行,只需设置初始值:

Person* ptrHead = NULL;

答案 1 :(得分:0)

  • 您使用指向指针pptrItem的指针。

  • 然后你做了作业

    *_item = _head;
    
  • 直到上述步骤一切正常。

  • 您通过

    释放了temp
    free(temp); 
    /* This means that _item now stores the address of object whose  
     * contents are already freed.
     */
    
  • 然后您可以访问已存储在已释放内存中的值

    printf("the removed item is:%d\n", (**pptrItem).m_id);
    
  • 但是嘿(**pptrItem).m_id目前还不存在。为了简化一点,请将*pptrItem替换为temp(此处temp是在函数Person* ListRemoveHead()中取消分配的内存块),然后它变为(*temp).m_id结果是分段错误。

<强>解决方法

将您的ListRemoveHead更改为以下内容

void ListRemoveHead(Person* _head) 
{
    int id;
    if(NULL == _head)
    {
        return NULL;
    }

    Person* temp;
    temp = _head;

    id=(*_head).m_id;

    _head = _head->m_next;

    free(temp);
    printf("The item removed is : %d\n",id);

}