Leerer vector löst debug error im destructor aus



  • Hallo!
    Ich habe folgendes Problem:
    Wenn ich mein Objekt, das einen vector<int*> enthält, "destruiere", löst dieser manchmal, aber nicht immer einen Debug Error aus. Die Meldung ist:

    Heap Corruption Detected: after Normal Block (#137) at 0x00EF7D0.
    CRT detected that the application wrote to memory after end of heap buffer.

    Was heisst das genau, was kann passiert sein? Zum Zeitpunkt des Destruierens ist der vector leer. Ich schreibe zwischenzeitlich ein paar Pointer auf int[3]-Speicherbereiche rein, die ich mit new angelegt habe, und delete die auch, wenn ich sie aus dem vector entferne. Bei einem anderen Projekt hat diese Methode immer funktioniert.
    Was kann mir der Debug Error sagen? In meinem Destructor ist nichts zu tun, der vector ist ein protected-member der Klasse, den vector fülle ich so:

    int* i=new int[3];//deleted in processSamples
    	i[0]=note;
    	i[1]=velocity;
    	i[2]=sampleOffset;
    	m_noteOnList.push_back(i);
    

    und leere ihn so:

    for(int i=0;i<m_noteOnList.size();i++)//Is there a note to play?
    		{
    			int* note=m_noteOnList.at(0);
    
    			m_noteOnList.erase(m_noteOnList.begin());
    			if(note[2]==0) //is it time to play?
    			{
    				playNote(note[0],note[1]);
    				delete[] note;//<--Entweder delete oder...
    			}
    			else
    			{
    				note[2]--;//decrease the deltaFrames (time to wait for the event)
    				m_noteOnList.push_back(note);//note not played, wait on
    //...zurück in die Liste
    			}
    		}
    

    Wie gesagt, zum Zeitpunkt des Destruktor aufrufs ist der Vector immer leer, wie es sein sollte.
    Kann mir da jemand helfen?
    Vielen Dank und viele Grüße
    Sören



  • zuerst einmal sieht das für mich so aus als würdest du immer vorne was rauslöschen und immer hinten was anfügen. vector ist dafür vielleicht nicht das geeignetste, versuchs mal mit deque<>.

    Dann sollte dir noch klar sein, dass die size() des containers sich ändert und dass die for-schleife vor jedem Aufruf size() nochmal aufrufst. Das zusammen mit der Zählvariablen die du garnicht benutzt bedeutet, dass du z.B. wenn du 4 elemente im container hast und alle gelöscht werden sollten, du nach 2 iterationen nurnoch 2 elemente im container hast und i = 2 ist - damit ist nichtmerh i< size() gegeben und die Schleife wird beendet, ohne dass der container leer ist.

    Wie ich das ganze ändern würde: nutze eine priority_queue (dein note[2] scheint ja sowas wie ne priorität zu sein, wenn du sie immer hinten anstellst) und ändere die schleife in sowas wie "while (! container.empty())"



  • pumuckl schrieb:

    Dann sollte dir noch klar sein, dass die size() des containers sich ändert und dass die for-schleife vor jedem Aufruf size() nochmal aufrufst. Das zusammen mit der Zählvariablen die du garnicht benutzt bedeutet, dass du z.B. wenn du 4 elemente im container hast und alle gelöscht werden sollten, du nach 2 iterationen nurnoch 2 elemente im container hast und i = 2 ist - damit ist nichtmerh i< size() gegeben und die Schleife wird beendet, ohne dass der container leer ist.

    ...Das ist genau die Funktionalität, die ich haben möchte. In meinem Programm tut sie auch genau das, was ich möchte. Das einzige Problem, das ich habe, ist, dass ich, wenn mein Objekt zerstört wird, einen Debug Error erhalte. Da das nur beim Beenden der Fall ist, kann es mir eigentlich auch egal sein, ist nur ein bisschen nervig und natürlich total unsauber.
    Zur Erklärung der Schleife: Die Gespeicherten Tripel stellen MIDI-Noten dar, die in einer Warteschleife (aussen drum rum) hängen. Es gibt, Notenhöhe ([0]), Anschlagstärke([1]) und eben "Wartezeit"[2]. Ist die Wartezeit abgelaufen, wird die Note gespielt, wenn nicht, wieder in den Vektor geschrieben und erstmal andere Funktionen ausgeführt. Vielleicht nicht der tollste Algortihmus dafür, hat sich aber bei mir bei anderen Projekten bewährt, wo der DebugError auch NICHT aufgetreten ist.
    Wenn mir jemand sagen könnte, was der Error zu bedeuten hat? Vielleicht kommt man dann eher dem Problem auf die Schliche...
    Grüße
    Sören



  • Ok, du hast zumindest in sofern recht, als dass ich nicht beachtet habe, dass .size() immer aufgerufen wird. Der Container muss aber trotzdem nicht leer werden innerhalb der Schleife. Vielleicht tritt der Bug immer dann nicht auf, wenn nur ein Element pro Schleifenaufruf (in allen durchgängen insgesamt) entfernt wird.
    Danke für den Hinweis!
    Grüße
    Sören



  • soerenP schrieb:

    Heap Corruption Detected: after Normal Block (#137) at 0x00EF7D0.
    CRT detected that the application wrote to memory after end of heap buffer.
    ...Bei einem anderen Projekt hat diese Methode immer funktioniert....
    Sören

    der fehler kann theoretisch ganz wo anders liegen gerade wenn es 1:1 bei nem anderen projekt funktioniert hat...bei mir war es z.b. mal eine map<string,void*>... da kam eben auch nur manchmal eine exception beim abfragen oder schreiben!! monate später nach aggressiven suchen hab ich den fehler gefunden und es war der bitmap lade code....in komplett anderen dateien und die include reihenfolge war entscheidend---ein #pragma pack hat den ganzen nachfolgenden code "kaputgemacht"... falls du auf unix/linux arbeitest probier mal valgrind. der fehler sagt in etwa dass dein programm an eine stelle schreibt wo nix mehr zugewiesen ist...sozusagen heap overflow...was aber auch von ganz wo anders im code "provoziert" sein kann....
    trotzdem würde ich es auch so wie pumuckl machen nimm ne priority_queue...mit vergleichs operator mit note[2] dann sind die noten schon sortiert nach deim einfügen und dann nimm einfach immer top und pop für den zugriff. falls es zeitabhängig is oder nicht immer die komplette liste durchlaufen werden soll mach anstatt von jeder note diese note[2] zu verringern zähle doch einfach 1 zähler(die zeit) hoch und durchlaufe nicht die gesammte queue sondern nur von top sozusagen so lange eins weggenehmen und abspielen bis "die zeit" noch passt...der rest muss ja noch nicht verarbeitet werden....
    hoffe das hilft schönen abend noch



  • Wie mach ich denn eine eigene priority_queue, also mit eigener compare funktion?
    Das hier will er nicht:
    bool myCompare(int*,int*);
    priority_queue<int*,vector<int*>,myCompare> queue;
    Ihm gefält myCompare nicht. Muss ich irgendeinen typedef machen, damit er myCompare als Parameter akzeptiert?
    Grüße
    Söre



  • soerenP schrieb:

    Wie mach ich denn eine eigene priority_queue, also mit eigener compare funktion?
    Das hier will er nicht:
    bool myCompare(int*,int*);
    priority_queue<int*,vector<int*>,myCompare> queue;

    du machst dazu nicht einfach eine funktion sondern einen operator und packst diesen in ein struct z.b.:
    struct myCompare {
    bool operator() (int* a, int* b) const { return .... }
    };

    in deinem fall warscheinlich return a[2]>b[2]; oder mit < je nachdem oder sowas in der art...


Anmelden zum Antworten