在我将“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.
答案 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);
}