"delete []" Aufruf im Destructor erzeugt "Heap Corruption"



  • Hallo,

    ich habe in meiner Klasse ein dynamisches Array vom Typ Int.
    Dieses wird im Constructor mit "jmp = new int[arrsize];" angelegt und soll im Destructor wieder gelöscht werden mit "delete [] jmp;".

    Nur leider schmiert das programm zur Laufzeit mit einer "Heap Corruption Detected" ab. Warum? Ohne das delete gehts zwar, ist aber ein ziemliches speicherleck 😉

    Merkwürdigerweise konnte ich zu dem Problem nichts finden.

    Hier der Code:

    HeaderDatei:

    #ifndef _kfromn_
    #define _kfromn_
    
    #include  <iostream>
    #include "Player.h"
    #include <math.h>
    using namespace std;
    class kfromn{
    	Card* arr;
    	int* jmp;
    	short arrsize;
    	int n,k, i, combinations, combisDone;
    	bool final;
    	int fac(int x);
    public:
    	kfromn(Card* arr, int n, int k);
    	~kfromn();
    	bool getNext(Card* cards);
    };
    
    #endif // _kfromn_
    

    QuellDatei:

    #include "stdafx.h"
    #include "kfromn.h"
    
    kfromn::kfromn(Card* arr, int n, int k){
    	this->arr = arr;
    	this->n = n;
    	this->k = k;
    	i = 0;
    	combinations = fac(n)/(fac(k)*fac(n-k));
    	combisDone = 0;
    	final = false;
    	if(n<=k)
    		return;
    	arrsize = n-k;
    	jmp = new int[arrsize];
    	for(short i=0; i<n-k;i++)
    		jmp[i]=i+1;
    	jmp[n-k-1]--;
    }
    kfromn::~kfromn(){
    
    	delete[]  jmp;//<--- hier kommt der fehler
    
    }
    bool kfromn::getNext(Card* cards){
    
    	if(combisDone>=combinations)
    		return false;
    	if(n==k)//results are the last k fields
    	{
    		short j = i;
    		while(j<i+n){
    			cards[j-i] = arr[j];
    			j++;
    		}
    		final = true;
    	}
    	else if(jmp[0]>=k+i){
    		//recursive call
    		n--;//convert problem from n over k possibilities to n-1 from k
    		i++;
    		jmp[0] = i+1;
    		for(short j=1; j<n-k;j++)//and reinitialize the jmp array
    			jmp[j]=i+j+1;
    		jmp[n-k-1]--;//dec because it gets inc later
    		return getNext(cards);
    	}
    	else
    	{
    		cards[0]= arr[i];
    		for(short j=n-k-1;j>=0;j--)
    		{
    			int dummy = jmp[j];
    			if(jmp[j]>=k+j+i)
    			{
    				if(j>0)
    					jmp[j] = jmp[j-1] + 2;
    			}
    			else
    			{
    				jmp[j]++;
    				break;
    			}
    		}
    		bool allow;
    		short m = 1, i = this->i+1;
    		while(m<k){
    			allow = true;
    			for(short j=n-k-1;j>=0;j--)
    				if(jmp[j]==i)
    					allow = false;
    			if(allow)
    			{
    				cards[m] = arr[i];
    				m++;
    			}
    			i++;
    		}
    	}
    	combisDone++;
    	return true;
    }
    
    int kfromn::fac(int x){
    	if(x<=0)
    		return 0;
    	else if(x>1)
    		return x*fac(x-1);
    	else 
    		return 1;
    }
    

    veio



  • keine lust mir den code jetzt anzutun, aber ich geb dir mal einen tipp:

    std::vector<int> jmp;
    

    http://www.sgi.com/tech/stl/Vector.html

    mein tipp ist aber, dass du dir den heap irgendwo woanders bereits zerschossen hast. Das heisst der Fehler liegt wahrscheinlich im aufrufenden Code.

    //edit
    Ich hab nochmal gegoogelt, zu dem Fehler gibt es ziemlich viel infostoff 🙂
    Im Endeffekt ist es so, dass du irgendwo auf Speicher zugreifst, den du nicht benutzen darfst, und das ganze geht erst später hoch. Mach ein paar Grenzwerttests und prüfe nach wo dein Algorithmus über die Arraygrenzen hinaus schreibt. Ergo Debug ne runde 🙂



  • das

    if(n<=k)
            return;
    

    vor dem new ist gefährlich

    wenn er hier abbricht erzeugt er nie ein int array wenn du es dann gelöscht wird dann bum.....

    wenn du es dennoch so machen willst, was ich nicht gut finde.. dann mach anfangs im konstruktor

    jmp=NULL;
    

    und im destruktor dann

    if(jmp) delete[] jmp;
    


  • Danke für die Antworten, mal schauen ob ich etwas bei den Grenzen falsch gemacht habe.

    Ist ein Vector genauso schnell? als ich den mal getestet habe, kam der mir wesentlich langsamer vor, kann aber auch woanders dran gelegen haben.



  • Im Debugmodus ist ein vector oft langsamer, da hier in vielen Implementationen mehr Prüfungen vorgenommen werden. Im Releasemodus (NDEBUG und Optimierungen) sollte der Unterschied kaum merkbar sein.

    Aber selbst wenn er vorhanden ist, liegt die Wahrscheinlichkeit erfahrungsgemäß bei > 80%, dass Du Dir zu früh über Optimierungen Gedanken machst 😉



  • Wenn Dir der Vektor zu lahm vorkommt übersetze mal ohne Debugg-Symbole.



  • Da du keinen Copy-Konstruktor geschrieben hast, steht da ein Compilergenerierter, der einfach die Werte kopiert.
    Mit dynamisch angelegten Speicher ist das immer böse. Implementier mal den Copy-Ctor richtig, oder deklarier ihn als private. (selbe mit operator=)

    Ich vermute ja dein problem ist folgendes:

    {
    kfromn test(...); //mach ein objekt test
    {
    kfromn test2(test); //mach test2 als kopie von test ("jmp" von test und test2 zeigen auf denselben speicher)
    } //führe destruktor von test2 aus ->speicher von "jmp" wird gelöscht
    } //führe destruktor von test aus ->speicher von "jmp" wird gelöscht - ups, der is ja schon weg - peng
    

    Wenn dein Problem woanders liegt, solltest du dich trotzdem drum kümmern, weil sowas gibt ziemlich oft Fehler, wenn nicht jetzt dann später.



  • BorisDieKlinge schrieb:

    wenn du es dennoch so machen willst, was ich nicht gut finde.. dann mach anfangs im konstruktor

    jmp=NULL;
    

    und im destruktor dann

    if(jmp) delete[] jmp;
    

    Da ein delete auf 0 (NULL) definiert ist, und einfach nichts tut, kann man mit einem sauber initialisierten Zeiger auch das "if(jmp)" weglassen. Wobei ich denoch Smartpointer (boost::scoped_ptr oder boost::shared_ptr - je nach Anwendungsfall) vorziehe 😉

    cu André



  • Es lag daran, dass ich auf ein -1. Array Feld zugriffen habe.


Log in to reply