2016-05-07 9 views
1

Aus irgendeinem Grund den Zugriff ich einen Segmentation Fault bekommen; Ich verwende einen Vektor von Zeigern, die auf ein Klassenobjekt zeigen. Im Grunde brauche ich einen Knoten, der einen Vektor von Zeigern zu anderen Knoten hat, in anderen, um ein Multigraph zu machen. Hier ist der relevante Teil meiner Code:Segmentation fault, wenn ein Zeiger-Mitglied-Funktion in einem Vektor

node.h:

#ifndef NODE_H 
#define NODE_H 

class node 
{ 
public: 
    string content() 
    vector<node*> next;  //causing the error 
    void add_arc(node a); 

    string rna_frag; 

#endif 

node.cpp:

void node::add_arc(node a) 
{ 
    node *b = &a; //b->content() works fine here 
    next.push_back(b); 
} 

string node::content() 
{ 
    return rna_frag; 
} 

main.cpp:

int main() 
{ 
    vector<node> nodes; 
    node a; 
    node b; 
    node c; 

    a.add_arc(b); 
    a.add_arc(c); 
    a.rna_string = "G"; 

    nodes.push_back(a); 
    nodes.push_back(b); 
    nodes.push_back(c); 

    cout << nodes[0].content() << endl; //prints "G", works fine 
    cout << nodes[0].next.size() << endl; // prints "2", works fine 
    cout << nodes[0].next[0]->content() << endl; //segmentation fault 
    //cout << nodes[0].next->content() << endl; //also segmentation fault 
    //cout << nodes[0].next[0]->rna_frag << endl; //also segmentation fault 
} 

In diesem Fall ist der String von Knoten [0] "G" und zeigt auf 2 andere Knoten, so dass die ersten 2 Couts perfekt funktionieren. Aber wenn ich auf den Inhalt des Vektors zugreife, stürzt er einfach ab und gibt einen Segmentierungsfehlerfehler. Wer weiß warum?

+0

_ „Hier ist der relevante Teil meines Codes“ _ Nein, Posten [MCVE].Sie sollten jetzt wissen, dass von Ihnen erwartet wird. –

+1

Wenn Sie 'vector.push_back (a)' tun, ist der Knoten im Vektor eine Kopie (gespeichert in einer anderen Speicheradresse). Darüber hinaus nimmt Ihr 'add_arc' seinen Parameter nach Wert und der Knoten, den Sie in den Vektor schieben, ist lokal für diese Funktion. Sobald dies der Bereich dieser Funktion deneferencing den Zeiger verlassen ist nicht definiert – user463035818

+0

@ tobi303: Warum beantworten Sie die Frage in den Kommentaren? Es gibt einen schönen Antwortabschnitt unten für Sie, um zu verwenden! –

Antwort

5

In add_arc Sie speichern die Adresse des Parameters a, die dann zerstört wird, wenn die Funktion beendet - so haben Sie das Verhalten nicht definiert.

Sie kopieren auch Knoten, wenn Sie nodes.push_back() nennen, die Sie verursachen eine Menge Ärger geht.

Sie müssen entweder aufhören zu kopieren oder schreiben Sie eine richtige Kopie Konstruktor (und folgen Sie dann die Regel von 3, oder 5).

+2

Ahh danke, ich habe vergessen, 'a' eine Referenz zu machen, ich werde deinen Rat zum Kopieren nehmen – xyz

2

Mit

void node::add_arc(node a) 
{ 
    vertex *b = &a; //b->content() works fine here 
    next.push_back(b); 
} 

Sie in next die Zeiger auf ein Objekt hinzuzufügen, das aus dem Verfahren (a) zerstört wird, zu verlassen.

es verwenden ...

cout << nodes[0].next[0]->content() << endl; 

Absturz!

Vorschlag: Transformation next in einem Vektor von Knoten (nicht von Knoten Zeiger)

2

Wenn Sie vector.push_back (a) der Knoten in dem Vektor ist eine Kopie (an einer anderen Speicheradresse gespeichert ist). Darüber hinaus nimmt Ihr add_arc seinen Parameter nach Wert und der Knoten, den Sie in den Vektor schieben, ist lokal für diese Funktion. Sobald dies verlassen Sie den Bereich dieser Funktion Dereferenzierung, dass Zeiger ist undefiniertes Verhalten.

Sie sollten durch Verweis das Argument übergeben, oder in diesem Fall noch einfacher ein Zeiger auf den Knoten, den Sie hinzufügen möchten, in Betracht ziehen. Aber auch dann muss man sich bewusst sein, dass in der Haupt dieser ...

vector<node> nodes; 
node a; 
node b; 

a.add_arc(b); 

nodes.push_back(a); 
nodes.push_back(b); 

wäre nicht, was Sie wollen, weil jetzt a hat b als Bogen hinzugefügt, während der zweite Eintrag der Knoten Vektor a kopieren von b. Vielleicht wäre es in diesem Fall einfacher, eine vector<node*> nodes zu verwenden, weil Sie Zeiger kopieren können und sie immer noch auf das gleiche Objekt zeigen.