2016-04-08 5 views
0

i ständig Segmentation fault bekommen, nachdem ich "ListRemoveHead" -Funktion, um den Code meiner verknüpften Liste hinzugefügt ...VerketteteListe - Segmentation fault (core dumped)

wenn ich auf Kommentar ListRemoveHead funktioniert der Code funktioniert gut, auch es scheint es mir die Segmentierung Fehler am Ausgang des Hauptes bekommen ...

könnten Sie mir bitte helfen, den Fehler zu finden ...

* aktualisiert mit - gDB-Ausgang, noch Fehlersegmentierung.


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

Startprogramm: /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 ([email protected]=0, listp=0xb7fbf3c4 <__exit_funcs>, [email protected]=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. 
+1

'* _item' zeigt auf einen freigegebenen Speicherblock. –

+0

Als eine Randnotiz, stammt der Coding-Fehler, den ich oben erwähnt habe wahrscheinlich von einem Designfehler - Sie haben nicht wirklich entschieden, was der Zweck dieser Funktion - ändern Sie den Kopf der Liste und speichern Sie den ursprünglichen Kopf oder ändern Sie den Kopf der Liste und geben Sie den zugewiesenen Speicher frei. –

+0

Das erste Argument zu 'CreatePerson()' ist völlig unnötig und sehr verwirrend. – unwind

Antwort

0

Es sieht aus, dass Sie diese Zeilen tauschen müssen in ListRemoveHead Funktion:

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

weil Sie geben einen ungültigen Zeiger (freigegeben) mit _item zurück.

Eigentlich später bemerkte ich, dass Sie die entfernte Artikel-ID drucken möchten. Dann sollten Sie den Code neu zu gestalten, damit es stattdessen statt nur id zurück:

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

nur nicht vergessen, den Rückgabewert im Haupt Code zu überprüfen:

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

aktualisieren

Sie greifen auch auf nicht initialisierten Speicher zu, weil Sie Haupt

haben

die nie initialisiert wird und am Ende der Liste wird. Also, Sie brauchen eigentlich diese Zeile nicht nur gesetzt Anfangswert:

Person* ptrHead = NULL; 
+0

ich entfernte den Teil ich frei * _item, meine Absicht ist es, den Kopf der Liste einen Knoten weiter zu bewegen, einen Zeiger auf den neuen Kopf zurück zu main, während die Informationen zu halten der entfernte Knoten in * _item. Wenn ich die Funktion auskommentieren, um den Kopf zu entfernen, ist alles in Ordnung, aber wenn ich es behalte, erhalte ich einen Segmentierungsfehler, nachdem main beendet ist. –

+0

@PeterBerger ja, das ist ein anderes Problem, siehe mein Update – pmod

0
  • Sie verwenden einen Zeiger pptrItem auf Zeiger.

  • Dann machen Sie eine Zuordnung

    *_item = _head; 
    
  • Bis die obigen Schritt die Dinge in Ordnung sind.

  • Sie befreit temp von

    free(temp); 
    /* This means that _item now stores the address of object whose 
    * contents are already freed. 
    */ 
    
  • Dann greifen Sie auf die der Wert in bereits gespeicherten Speicher in

    befreit
    printf("the removed item is:%d\n", (**pptrItem).m_id); 
    
  • Aber hey (**pptrItem).m_id existiert nicht im Moment. Um die Dinge ein wenig zu vereinfachen, ersetzen Sie *pptrItem durch temp (Hier ist die temp ist der Speicher Chunk, die in der Funktion Person* ListRemoveHead() freigegeben ist), dann wird es (*temp).m_id und das Ergebnis ist Segmentierung Fehler.

Abhilfe

Ändern Sie Ihre ListRemoveHead um so etwas wie unten

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); 

} 
+0

ich entfernte den Teil ich frei * _item, meine Absicht ist es, den Kopf der Liste einen Knoten weiter zu bewegen, einen Zeiger auf den neuen Kopf zurück, während die Informationen behalten des entfernten Knotens in * _item. Wenn ich die Funktion auskommentieren, um den Kopf zu entfernen, ist alles in Ordnung, aber wenn ich es behalte, erhalte ich einen Segmentierungsfehler, nachdem main beendet ist. –

+0

Was meinst du mit 'den Kopf entfernen'? Meinst du damit den Raum freizugeben? 'aber wenn ich es behalte, erhalte ich einen Segmentierungsfehler' Der Segmentierungsfehler ist auf den fünften Punkt in dieser Antwort zurückzuführen. Es wird empfohlen, dass Sie den Speicherplatz für entfernte Objekte freigeben können, insbesondere wenn die Liste groß ist. Sie dürfen jedoch auf keine der Objektelemente zugreifen, nachdem das Objekt entfernt oder "freigegeben" wurde. – sjsam