"std::bad_alloc": bin ich mit zu viel Speicher?
Die Meldung:
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
Sah ich den gdb backtrace und dies ist das niedrigste level-Methode, die ich umgesetzt habe:
/*
* get an array of vec3s, which will be used for rendering the image
*/
vec3 *MarchingCubes::getVertexNormalArray(){
//Used the same array size technique as getVertexArray: we want indices to match up
vec3 *array = new vec3[this->meshPoints.getNumFaces() * 3]; //3 vertices per face
int j=0;
for (unsigned int i=0; i < (this->meshPoints.getNumFaces() * 3); i++) {
realVec normal = this->meshPoints.getNormalForVertex(i);
// PCReal* iter = normal.begin();
if (normal.size() >= 3) {
array[j++] = vec3(normal[0], normal[1], normal[2]);
}
cout << i << " ";
}
return array;
}
Die cout-Anweisung, die Sie oben sehen, zeigt an, dass es beendet nach 7000+ Iterationen.
Die obige Funktion wird aufgerufen, nur einmal in der Nähe des Ende meiner Bewerbung. Nenne ich eine sehr ähnliche Funktion vor dem Aufruf der oben genannten, nicht zu Problemen führen.
- Haben Sie jemals frei die Felder, die von dieser Funktion zurückgegeben, die mit
delete[]
? - Wie groß ist
meshPoints.getNumFaces()
? Und wie groß istvec3
? - Oh, ich bin es nicht. Und ich bin auch wieder eine gleich große Arrays aus einem anderen Verfahren. Also Geb ich das mal probieren.
- Autsch, dann haben Sie massive memory leaks. Übrigens solltest du smart pointers oder standard-Container; Sie sollten es vermeiden, vollständig manuelle Speicherverwaltung in C++, der code wird nicht exception-sicher und du wirst immer die Gefahr von Speicherlecks.
- ist 14,368. vec3 enthält 3 GLfloat ist.
- durch die Verwendung eines standard-container-Sie sind auch weniger wahrscheinlich wegwerfen, die Anzahl der gültigen Elemente (Sie haben zur Verfügung als
j
, dann werfen Sie es einfach Weg) - OK, unter der Annahme einer GLfloat ist 4 bytes (wie ein normaler C float, IEEE single), dann Sie versuchte zu vergeben 7000*14368*3*3*4 bytes, 3.45 GB, nur für den arrays.
- Ich kann nicht löschen das array, wenn es sich beendet, bevor Sie zurückgegeben wird, kann ich (endet auf 7000 aus (14000*3))?
- Nein, er ist die Zuweisung 14368 * 3 * 3 * 4 er
new
s vor der Schleife. Der Ruf, den wirft, wird wahrscheinlich inthis->meshPoints.getNormalForVertex(i);
- es bricht" - was ist das Thema hier? :S
- trotzdem, müssen Sie
delete
es, wenn Sie fertig sind es zu benutzen. Hier wäre es die Aufgabe des Aufrufers, es zu tun, aber Bedenken Sie, dass die wirkliche Lösung ist, entweder für die Verwendung der smart Pointer entweder "real" - Container. - Sollten Sie nicht löschen, das array, bevor es zurückgegeben wird, sollten Sie es löschen, wenn es nicht mehr benötigt wird. Das heißt, irgendwo im code die Funktion aufrufen. Betrachten Sie es als eine Tafel: Sie schreiben Daten auf das blackboard, aber Sie nie wischen Sie die Tafel, um Platz für neue Daten (
delete[]
). Wenn Sie das tun, lange genug, irgendwann gibt es keinen Ort mehr auf der Tafel. Aber man sollte nicht wischen Zeug von der Tafel, die Sie noch benötigen; nur Sachen die nicht mehr benötigt werden. - Dieses array wird zurückgegeben und an eine GL vertex-shader-Programm, so bin ich ein wenig vorsichtig, wenn ich es nicht mehr benötige. Dies ist einer der letzten wichtigen Dinge, die passiert in meiner Anwendung, so würde ich einfach löschen am Ende?
- Ah, ich sehe, dass ich falsch gelesen. Ich dachte, es war nach über 7000 Aufrufe.
- Löschen Sie am Ende nicht hilft. Da ich (naja, eigentlich jrok) jetzt bemerkt, dass hatte ich falsch gelesen: Wie oft haben Sie rufen diese Funktion, bevor es ausfällt?
- Eine weitere Idee, die in eine ganz andere Richtung: Haben Sie überprüft, dass
j
bleibt immer untenmeshPoint.getNumFaces()*3
? Vielleicht bekommen Sie diebad_alloc
durch einen Pufferüberlauf überschrieben wesentlichen heap-Strukturen. - Nur einmal. Ich bekomme auch eine gleich große array direkt vor dem Aufruf der oben genannten, einmal. Ich habe festgestellt, dass die Funktion nicht, zu Problemen führen. Ich werde es auf meine Frage.
- Ah, OK, dann ist das wahrscheinlich nicht dein problem. Löschen am Ende des Programms nicht unbedingt notwendig, da am Ende des Programms das OS nimmt den Speicher aus dem Programm sowieso, und das array enthält nur schwimmt, also fehlen dir keine Destruktor-Aufrufe. Also, was über
j
? - Ok, ich habe gerade bemerkt, dass
j
kann nicht größer sein alsi
, nicht größer als etwa 7000. Was bedeutetgetNormalForVertex
tun? - Ich Schätze Sie kleben mit mir-sollten wir uns bewegen, zu chatten oder so?
- lassen Sie uns weiter, diese Diskussion im chat
Du musst angemeldet sein, um einen Kommentar abzugeben.
(verschieben/erweitern aus den Kommentaren)
Da Sie die Zuweisung ein neues array-jedes mal, ohne seine Zuordnung aufgehoben wird, haben Sie ein massives Speicherleck, D. H. Sie weiter Fragen Arbeitsspeicher des Systems zu, ohne jemals geben es zurück. Schließlich wird der Speicherplatz auf dem heap abgeschlossen ist, und bei der nächsten Zuteilung das, was Sie bekommen ist ein
std::bad_alloc
Ausnahme.Den "C-Stil" Lösung wäre, sich zu erinnern freigeben solche Speicher, wenn Sie nicht mehr brauchst (mit
delete[]
), aber, das ist (1) fehleranfällig (man denke z.B. wenn Sie mehrere return-Wege innerhalb einer Funktion) und (2) potenziell Ausnahme-unsicher (jeder Befehl wird zu einem potenziellen return path, wenn Sie Ausnahmen!!!). So, auf diese Weise sollte vermieden werden.Die idiomatischen C++ - Lösung ist zu verwenden entweder intelligente Zeiger - kleine Objekte Kapseln den Zeiger und den zugehörigen Speicher freigeben, wenn Sie zerstört werden, oder standard-Container, die mehr oder weniger die gleiche Sache, aber mit copy-Semantik und einige mehr Glocken und Pfeifen (insbesondere die Speicherung die Größe des Arrays in Ihnen).
Ich habe diesen Fehler versucht zu reservieren, eine negative Länge array:
double myArray = new double[-9000];
Nur für den Fall, es hilft jemand.
std::bad_alloc
.std::bad_alloc
. Sie sind nicht versuchen zu reservieren, alles mit einem Zugang. Es ist ein gigantisch memory leak in der OP-code, das ist die offensichtliche Ursache der Zuordnung scheitern.std::bad_alloc
oderstd::eat_my_shorts
oderstd::stop_arguing
, aber in der Praxis werden Sie nicht bekommen, einestd::bad_alloc
von out-of-bounds-Lesezugriff. Wieder, die OP ist das problem eklatant offensichtlich ein Speicher-Leck, und dies bereits mehrere Male hier. Ich bin fertig, darüber zu streiten.Mein problem war, dass
this->meshPoints.getNormalForVertex(i)
greift auf ein array (oder vector, ich kann mich nicht erinnern), dessen Länge weniger alsthis->meshPoints.getNumFaces() * 3
. So war es den Zugriff auf die out-of-bounds.