2017-11-04 2 views
1

Ich arbeite an einem Programm in C++, das mit Graphen befasst ist.Speicher schreiben Ausnahme beim Erstellen eines Diagramms

I speichern Graph als Adjazenzliste von Knoten, und ich habe die entsprechenden Strukturen in .h-Datei erklärt, wie folgt:

typedef struct Node { 
    int val; 
    struct Node * next; 
} node; 

typedef struct Graph { 
    int v; 
    node ** arr; 
    node ** arr2; // reserved list for a reversed directed graph. 
} graph; 

Ich habe eine Funktion für einen Graphen Initialisieren wie folgt definiert:

graph * creategraph(int v) { // v == number of vertices 
    int i; 
    graph * temp = (graph*)malloc(sizeof(graph)); 
    temp->v = v; 
    for(i = 0; i < v; i++) { 
     temp->arr = (node**)malloc(v*sizeof(node*)); 
    } 
    for(i = 0; i < v; i++) { 
     temp->arr[i] = NULL; 
    } 
    return temp; 
} 

ich nenne die Funktion, wie unten gezeigt ein Diagramm mit Anzahl der Ecken zu erstellen, die gleich num_vertices:

graph * g = creategraph (num_vertices); 

Mit num_vertices gleich 200000 wird die Ausnahme "Access Violation Writing Location" in graph * createGraph bei der ersten Ausführung von ausgelöst.

Könnte mir jemand sagen, was ist das Problem hier? Vielen Dank.

+0

Bitte geben Sie weitere Einzelheiten an. Ich habe deinen Code ausprobiert und er läuft ohne Probleme sogar mit num_vertices = 999999 (obwohl die App ungefähr 10 GB RAM verbraucht hat). Wie viel RAM hast du? Vielleicht hast du keinen Widder mehr? Außerdem müssen Sie überprüfen, was malloc zurückgibt (wenn 0 zurückgegeben wird, wird der Speicher nicht zugewiesen und Sie müssen Ihre Schleifen stoppen). –

Antwort

3

ist ein großes Problem:

for(i = 0; i < v; i++) { 
    temp->arr = (node**)malloc(v*sizeof(node*)); 
} 

Dieser ordnet Platz für v Knoten, aber Sie haben nur einen Zeiger auf das letzte Sie zugeordnet. Dies ist ein Speicherleck. Was Sie tun müssen, ist dies:

temp->arr = (node**)malloc(v*sizeof(*temp->arr)); 
for(i = 0; i < v; i++) { 
    temp->arr[v] = (node*)malloc(sizeof(*temp->arr[0])); 
} 

Erläuterung:

arr Zeiger auf Node auf Zeiger ist. Zuerst müssen wir Speicher für v Zeiger zuweisen. Dann müssen wir Speicher für eine Node für jede dieser Zeiger zuweisen.

Beachten Sie auch, dass es unnötig (und daher schlecht) ist, malloc in C zu schreiben. Wenn Sie C++ codieren, ist es notwendig, also wenn Sie "C" codieren, aber einen C++ - Compiler verwenden das Ergebnis.

Nebenbei bemerkt:

Es ist gut, Praxis int arr = malloc(n*sizeof(*arr)) oder int arr = malloc(n*sizeof(arr[0])) statt int arr = malloc(n*sizeof(int)) zu schreiben. Der Grund ist, dass wenn Sie in Zukunft entscheiden, dass Sie long anstelle von int verwenden möchten, müssen Sie es nicht an mehr als einem Ort ändern.

+0

Kleinere Details: 'temp-> arr = malloc (v * sizeof (temp-> arr));' - >> 'temp-> arr = malloc (v * sizeof * temp-> arr);' (Sie könnten argumentieren, dass ein Zeiger die gleiche Größe wie ein Zeiger auf den Zeiger hat, aber immer noch ...) – wildplasser

+0

@klutt @Martin wenn ich versuche, das Casting zu entfernen, wird es nicht kompilieren und sagen, dass es 'void *' nicht dem Knoten (oder 'graph *') zuweisen kann ... –

+1

In diesem Fall kompilieren Sie C als C++. –

3

Das Problem ist, dass Sie temp->arrv Mal unnötig zuweisen und alle vorherigen Zuordnungen undicht, so dass Sie v mal so viel Speicher verwenden, wie Sie benötigen. Sie müssen es nur einmal zuweisen, also entfernen Sie die Schleife.

Don't cast the return value of malloc(), während Sie gerade dabei sind. Hier

Verwandte Themen