2016-08-09 183 views
0

Lernen Sie C++ kennen und versuchen Sie, eine Klasse so zu erstellen, dass sie mit Ints und Pointers für eine Struktur arbeitet. Die Ausgabe ist wie erwartet, aber das Testen mit Valgrind scheint ein Speicher-Lauch zu sein, aus einem unfertigen Speicher.Speicherleck mit Vorlage für Zeiger und Ints. Was mache ich falsch?

Ich glaube, es hat etwas damit zu tun, wie ich die Listenvariable in der Klasse init deklariere.

Was vermisse ich und wie kann ich es beheben? Danke.

#include <stdio.h> 

template <class T> 
class List { 
    T* list; 

public: 
    int length; 

    List(int len) { 
     list = new T[len]; 
     length = len; 
    } 

    virtual ~List() { 
     delete[] list; 
    } 

    T get(int index) { 
     return list[index]; 
    } 

    void set(int index, T val) { 
     list[index] = val; 
    } 
}; 
/* 
    You shouldn't change the code below, unless you want to _temporarily_ change the main function while testing. 
    Change it back when you're done. 
*/ 
typedef struct Point_ { 
    int x; 
    int y; 
} Point; 

int main(){ 
    List<int> integers(10); 
    for(int i = 0; i < integers.length; i++){ 
     integers.set(i, i * 100); 
     printf("%d ", integers.get(i)); 
    } 
    printf("\n"); // this loop should print: 0 100 200 300 400 500 600 700 800 900 

    List<Point *> points(5); 
    for(int i = 0; i < points.length; i++) { 
     Point *p = new Point; 
     p->x = i * 10; 
     p->y = i * 100; 
     points.set(i, p); 
     printf("(%d, %d) ", points.get(i)->x, points.get(i)->y); 
     delete p; 
    } 
    printf("\n"); // this loop should print: (0, 0) (10, 100) (20, 200) (30, 300) (40, 400) 
} 

mit g ++ kompiliert wie folgt aus:

g++ -Wall p2_templates.cpp -o p2_templates 

Gebrauchte valgrind mit diesem Befehl:

valgrind --tool=memcheck ./p2_templates 

dieses Ergebnis aus valgrind Anfahrt:

==22396== Memcheck, a memory error detector 
==22396== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al. 
==22396== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info 
==22396== Command: ./p2_templates 
==22396== 
0 100 200 300 400 500 600 700 800 900 
(0, 0) (10, 100) (20, 200) (30, 300) (40, 400) 
==22396== 
==22396== HEAP SUMMARY: 
==22396==  in use at exit: 72,704 bytes in 1 blocks 
==22396== total heap usage: 9 allocs, 8 frees, 73,848 bytes allocated 
==22396== 
==22396== LEAK SUMMARY: 
==22396== definitely lost: 0 bytes in 0 blocks 
==22396== indirectly lost: 0 bytes in 0 blocks 
==22396==  possibly lost: 0 bytes in 0 blocks 
==22396== still reachable: 72,704 bytes in 1 blocks 
==22396==   suppressed: 0 bytes in 0 blocks 
==22396== Rerun with --leak-check=full to see details of leaked memory 
==22396== 
==22396== For counts of detected and suppressed errors, rerun with: -v 
==22396== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) 
+1

Warum nicht einfach einen 'Vektor' verwenden? –

+0

Was ist 'points.length'? –

+0

Warum ist dein Destruktor "virtuell"? –

Antwort

3

Vor allem Lese die Valgrind-Ausgabe VERY SORGFÄLTIG und VOLLSTÄNDIG (und alles tun, was Valgrind empfiehlt). In Ihrem Fall sind die Fragmente von Interesse:

Rerun mit --leak-check = full Details durchgesickert Speicher zu sehen

noch erreichbar: 72.704 Bytes in 1 Blöcken

Sie sollten auch Folgendes beachten: http://valgrind.org/docs/manual/faq.html#faq.reports (4.1. Mein Programm verwendet die C++ STL und String-Klassen. Valgrind Berichte 'immer noch erreichbar 'Speicherlecks mit diesen Klassen am Ausgang des Programms, aber es sollte keine geben).

Und wenn Sie Zeit haben, können Sie von einem detaillierten Verständnis davon profitieren: http://valgrind.org/docs/manual/mc-manual.html#mc-manual.leaks (4.2.8. Speicherlecksuche).

Endlich können Sie Tonnen von nützlichen Informationen hier finden: http://valgrind.org (valgrind homepage).

1

Ein starkes Verständnis der grundlegenden Datenstrukturen ist gut! Ich ermutige Sie, es vollständig zu erforschen. Sobald Sie die Grundlagen beherrschen, kann die STL sehr nützlich sein, um sich um die anstrengende Arbeit zu kümmern, während Sie über die harten Probleme nachdenken.

Es gibt keine Lecks in Ihrem Code. Valgrind sieht die Speicher an anderer Stelle, wie bereits erwähnt, können Sie den --leak-check = full verwenden, um weitere Details zu erhalten. Es ist gut, dass Sie versuchen, diese Details zu verstehen.

Dies ist jedoch ein Problem mit einem ungeeigneten Zeiger.

#include <stdio.h> 

template <class T> 
class List { 
    T* list; 

public: 
    int length; 

    List(int len) { 
     list = new T[len]; 
     length = len; 
    } 

    virtual ~List() { 
     delete[] list; 
    } 

    T get(int index) { 
     return list[index]; 
    } 

    void set(int index, T val) { 
     list[index] = val; 
    } 
}; 
/* 
    You shouldn't change the code below, unless you want to _temporarily_ change the main function while testing. 
    Change it back when you're done. 
*/ 
typedef struct Point_ { 
    int x; 
    int y; 
} Point; 

int main(){ 
    List<int> integers(10); 
    for(int i = 0; i < integers.length; i++){ 
     integers.set(i, i * 100); 
     printf("%d ", integers.get(i)); 
    } 
    printf("\n"); // this loop should print: 0 100 200 300 400 500 600 700 800 900 

    List<Point *> points(5); 
    for(int i = 0; i < points.length; i++) { 
     Point *p = new Point; 
     p->x = i * 10; 
     p->y = i * 100; 
     points.set(i, p); 
     printf("(%d, %d) ", points.get(i)->x, points.get(i)->y); 
     delete p; 
    } 
    Point* fail = points.get(0); 
    fail->x = 0; 
    fail->y = 0; 
    printf("\n"); // this loop should print: (0, 0) (10, 100) (20, 200) (30, 300) (40, 400) 
} 

Beachten Sie, dass ich nach der Punktschleife die Variable 'fail' hinzugefügt habe, um das Problem zu demonstrieren. Die points-Variable wird deklariert und gut gefüllt, aber der Inhalt wird gelöscht. Die Liste enthält den Punkt * und nicht den Punkt, so dass beim Löschen der Zeiger in der Liste "hängt". Die Verwendung von Dangling-Pointern wird den Heap fast jedes Mal zum Absturz bringen oder beschädigen. Dies ist ein häufiges Problem mit den STL-Containern, wenn Zeiger gehalten werden.

Ein großer Fehler in C++ ist die Heap-Verwaltung. Die korrekte Verwendung des Heapspeichers ist sehr schwierig, da das größte Problem die Besitzübergabe ist. Dangling Pointer oder Leaks resultieren häufig aus Verwirrung darüber, wem der Zeiger gehört. Es gibt hier einen kurzen Artikel Avoiding Leaks in C++

Das Ausführen dieses Programms unter Valgrind zeigt ungültige Schreibfehler. Versuche es.

+0

Ich habe den Valgrind-Test mit den vorgeschlagenen Flags ausgeführt und Schreibfehler bekommen. –

+0

Rechts. Speicherverwaltung ist in C++ schwierig. Würde mich freuen, wenn meine Antwort hilfreich wäre. Danke –

+0

@ or.ohev-zion Eine Abstimmung oben würde geschätzt werden, wenn meine Antwort hilfreich war. –