Memory Leaks



  • Hallo,

    ich habe Probleme in meiner fertigen MDI Anwendung:
    Nach dem Beenden des Programms werden folgende Fehlermeldungen diesen Typs angezeigt:
    Detected memory leaks!
    Dumping objects ->
    c:\dokumente und einstellungen\rafael\eigene dateien\visual studio projects\gwp\w32d\syntaxcolorizer.cpp(166) : {661} normal block at 0x018C1CF8, 4 bytes long.
    Data: <GWP > 47 57 50 00

    Wie kann man diese Memory Leaks am einfachsten entfernen?
    Für Eure Hilfe bin ich sehr dankbar!

    Gruß 😉



  • #ifdef _DEBUG 
    #define new DEBUG_NEW 
    #undef THIS_FILE 
    static char THIS_FILE[] = __FILE__; 
    #endif
    

    Das notiert sich zu jedem new-Aufruf die Programmzeile - anschließend erhältst du etwas klarere Angaben, woher das Lack stammt.

    Edit: Offenbar hast du das schon aktiviert 😉 Schau doch mal in Zeile 166 der syntaxcolorize.cpp, was dort mit new angelegt wird - und such das zugehörige delete.



  • Vielen Dank für den Tip.

    Diesen Code habe ich bereits schon in meiner cpp Datei enthalten.
    Wenn ich doppelt auf den Fehler klicke werde ich auf die 2. Zeile des folgenden Quellcodes verwiesen:

    void CSyntaxColorizer::addKey(LPCTSTR Keyword, CHARFORMAT cf, int grp) //add in ascending order
    {
    	SKeyword* pskNewKey = new SKeyword;
    	SKeyword* prev,*curr;
    
    	//the string pointed to by Keyword is only temporary, so make a copy 
    	// of it for our list
    	pskNewKey->keyword = new TCHAR[strlen(Keyword)+1];
    	strcpy(pskNewKey->keyword,Keyword);
    
    	pskNewKey->keylen = strlen(Keyword);
    	pskNewKey->cf = cf;
    	pskNewKey->group = grp;
    	pskNewKey->pNext = NULL;
    	*(m_pTableZero + pskNewKey->keyword[0]) = KEYWORD;
    

    Die Fehlermeldung lautet:

    c:\dokumente und einstellungen\dirk\eigene dateien\visual studio projects\gwp_02.11.05\w32d\syntaxcolorizer.cpp(167) : {363} normal block at 0x003C8B40, 76 bytes long.
    Data: < |< < > 88 7C 3C 00 05 00 00 00 3C 00 00 00 0F 00 00 F8



  • Ist dahinter die Funktion schon zu Ende 😕

    Du solltest vermutlich pskNewKey entweder irgendwo speichern (bzw. ans Hauptprogramm zurückgeben) oder vor dem return wieder freigeben (delete).



  • Nein, das war nur ein Teil aus der Funktion.

    Hier kommt die gesamte Funktion:

    void CSyntaxColorizer::addKey(LPCTSTR Keyword, CHARFORMAT cf, int grp) //add in ascending order
    {
    	SKeyword* pskNewKey = new SKeyword;
    	SKeyword* prev,*curr;
    
    	//the string pointed to by Keyword is only temporary, so make a copy 
    	// of it for our list
    	pskNewKey->keyword = new TCHAR[strlen(Keyword)+1];
    	strcpy(pskNewKey->keyword,Keyword);
    
    	pskNewKey->keylen = strlen(Keyword);
    	pskNewKey->cf = cf;
    	pskNewKey->group = grp;
    	pskNewKey->pNext = NULL;
    	*(m_pTableZero + pskNewKey->keyword[0]) = KEYWORD;
    
    	//if list is empty, add first node
    	if(m_pskKeyword == NULL)
    		m_pskKeyword = pskNewKey; 
    	else
    	{
    		//check to see if new node goes before first node
    		if(strcmp(Keyword,m_pskKeyword->keyword) < 0)
    		{
    			pskNewKey->pNext = m_pskKeyword;
    			m_pskKeyword = pskNewKey;
    		}
    		//check to see if new keyword already exists at the first node
    		else if(strcmp(Keyword,m_pskKeyword->keyword) == 0)
    		{
    			//the keyword exists, so replace the existing with the new
    			pskNewKey->pNext = m_pskKeyword->pNext;
    			delete m_pskKeyword->keyword; delete m_pskKeyword;
    			m_pskKeyword = pskNewKey;
    		}
    		else
    		{
    			prev = m_pskKeyword;
    			curr = m_pskKeyword->pNext;
    			while(curr != NULL && strcmp(curr->keyword,Keyword) < 0)
    			{
    				prev = curr;
    				curr = curr->pNext;
    			}
    			if(curr != NULL && strcmp(curr->keyword,Keyword) == 0)
    			{
    				//the keyword exists, so replace the existing with the new
    				prev->pNext = pskNewKey;
    				pskNewKey->pNext = curr->pNext;
    				delete curr->keyword; delete curr;
    			}
    			else
    			{
    				pskNewKey->pNext = curr;
    				prev->pNext = pskNewKey;
    			}
    		}
    	}
    }
    


  • Bau mal in deinen Destruktor eine Schleife ein, die die komplette Keyword-Liste aufräumt, wenn das Objekt gelöscht wird.



  • Das habe ich schon probiert.
    Ich habe im Destruktor Clear Keywordlist aufgerufen.
    Der Quellcode:

    void CSyntaxColorizer::ClearKeywordList()
    {
    	SKeyword* pTemp = m_pskKeyword;
    
    	while(m_pskKeyword != NULL)
    	{
    		*(m_pTableZero + m_pskKeyword->keyword[0]) = SKIP;
    		if(_stricmp(m_pskKeyword->keyword,"rem") == 0)
    			*(m_pTableTwo + '\n') = SKIP;
    		pTemp = m_pskKeyword->pNext;
    		delete m_pskKeyword->keyword;
    		delete m_pskKeyword;
    		m_pskKeyword = pTemp;
    	}
    }
    

    Bei der Programmausführung wird der Debugger mit einer Fehlermeldung:
    "Unbehandelte Ausnahme" unerbrochen und springt die MFC interne Datei free.c auf die Zeile: HeapFree(_crtheap, 0, pBlock); 😞



  • array new und scalares delete gehen nicht gut zusammen, auch wenn das hier sicher nicht das problem ist. Im übrigen könnte man beides sparen, wenn CString benutzt würde.

    Paule 0 schrieb:

    Bei der Programmausführung wird der Debugger mit einer Fehlermeldung:
    "Unbehandelte Ausnahme" unerbrochen und springt die MFC interne Datei free.c auf die Zeile: HeapFree(_crtheap, 0, pBlock); 😞

    benutz den callstack um den aufrufer (und die parameter beim aufruf) festzustellen.



  • Achja, nochwas: Hat es einen Grund, daß du die verkettete Liste selber implementierst? Ich würde dir dafür eher std::list oder std::set (oder die MFC-Versionen davon) empfehlen.



  • Die Keywordlist enthält meine selbsterstellten Schlüsselwörter.
    Ich weiß nicht wie ich das anders lösen könnte. 😕



  • ich würde std::map empfehlen



  • class SKeyWord
    {
      //...
      char* keyword;
      bool operator<(const SKeyWord& other)
      {return strcmp(keyword,other.keyword)<0;}
      //oder besser gleich:
    
      std::string keyword;
      bool operator<(const SKeyWord& other)
      {return keyword<other.keyword;}
    };
    
    class CSyntaxColorizer
    {
      std::set<SKeyWord> m_KeyWords;
      //...
    };
    
    //Im Quelltext:
    m_KeyWords.insert(newKWD);//einfügen
    m_KeyWords.erase(newKWD); //löschen
    //...
    


  • Entschuldige, dass ich mich jetzt twas blöd anstelle, aber wo soll ich das genau reinschreiben.
    Muß ich eine neue Klasse SKeyWord erstellen?
    Danke!



  • #include <map>

    und anstelle deiner eigenen Liste benutz du die std::map



  • Nein, du mußt deine vorhandene SKeyWord-Klasse entsprechend anpassen (für sets/maps benötigst du einen Vergleichsoperator - und eine vordefinierte String-Klasse ist einfacher zu handhaben als char*).



  • beschäftige dich algemein mit associativen standard-containern - dann wird vieles klarer - und deine addKey() methode u.ä. kannst du dann auf 0 zeilen eindampfen 😉

    anonsten kannst du nat. auch versuchen den fehler zu finden, ich kann ihn nicht entdecken (abgesehen vom delete[] auf ->keyword und das führt bei vc++ häufig nicht zu abstürzen), allerdings schaue ich es mir auch nicht besonders intensiv an


Anmelden zum Antworten