HEAP[Test.exe]: Invalid address specified to RtlValidateHeap( 00260000, 00263380 )



  • Hallo,

    ich habe eine Funktion geschrieben, die eine Combobox leeren soll. Der Aufruf verursacht jedoch den im Titel gennanten Fehler. Ich habe schon ein wenig gesucht, jedoch keine Antwort auf mein Problem gefunden. Hier stand z.B., dass die DLL und die EXE eventuell nicht mit der DLL Version der CRT gelinkt sind (Martin Richter). Und hier habe ich ähnliches erfahren, nur welche Option soll ich bei Projekteigenschaften->C/C++->Codegenerierung->Laufzeitbibliothek auswählen?

    Hier die Funktion, die die Probleme verursacht:

    HRESULT ClearComboBox(HWND hDlg, int IDDlgItem)
    {
    	int ItemCount = (int) (SendDlgItemMessage(hDlg, IDDlgItem, CB_GETCOUNT, 0, 0));
    	void* Data;
    
    	for (int i=0; i < ItemCount; ++i)
    	{
    		Data = (void*) (SendDlgItemMessage(hDlg, IDDlgItem, CB_GETITEMDATA, i, 0));
    		if (Data != (void*) (CB_ERR) && Data != NULL) free(Data);
    	}
    
    	SendDlgItemMessage(hDlg, IDDlgItem, CB_RESETCONTENT, 0, 0);
    
    	return S_OK;
    }
    

    Das free in Zeile 9 verursacht letztendlich die Heap Corruption.

    Vielen Dank im Voraus.



  • was wird den mit CB_SETITEMDATA übergeben?



  • Also es natürlich möglich, dass du da einen komplexeren Fall vorliegen hast, aber ich würde jetzt trotzdem spontan erstmal wissen wollen, wie du die ItemData-Teile erzeugst und da reinbastelst etc... Also ob das eher ein Problem im eigenen Code ist.



  • msdn schrieb:

    was wird den mit CB_SETITEMDATA übergeben?

    Verschiedenes (von Combobox zu Combobox unterschiedlich), meistens int-Werte.

    Decimad schrieb:

    Also es natürlich möglich, dass du da einen komplexeren Fall vorliegen hast, aber ich würde jetzt trotzdem spontan erstmal wissen wollen, wie du die ItemData-Teile erzeugst und da reinbastelst etc... Also ob das eher ein Problem im eigenen Code ist.

    Hier mal eine Funktion:

    HRESULT InitAdapterComboBox(HWND hDlg)
    {
    	ClearComboBox(hDlg, IDC_ADAPTERBOX);
    
    	int AdapterCount = D3DTemp->GetAdapterCount();
    	D3DADAPTER_IDENTIFIER9* Adapters = new D3DADAPTER_IDENTIFIER9[AdapterCount];
    
    	for (int i=0; i < AdapterCount; ++i)
    	{
    		if (FAILED(D3DTemp->GetAdapterIdentifier(i, 0, &Adapters[i])))
    		{
    			MessageBox(NULL, "Adapterinformationen konnten nicht abgefragt werden!", "Fehler", NULL);
    			delete [] Adapters;
    			return E_FAIL;
    		}
    
    		SendDlgItemMessage(hDlg, IDC_ADAPTERBOX, CB_ADDSTRING, 0, (LPARAM) Adapters[i].Description);
    		SendDlgItemMessage(hDlg, IDC_ADAPTERBOX, CB_SETITEMDATA, i, (LPARAM) i);
    	}
    
    	SendDlgItemMessage(hDlg, IDC_ADAPTERBOX, CB_SETCURSEL, 0, 0);
    
    	delete [] Adapters;
    
    	return S_OK;
    }
    


  • Nun übergibst du ja mit CB_SETITEMDATA überhaupt kein alloziertes Objekt, sondern einen bloßen index-integer, den versuchst du zu free'n?

    Oder ist das ein Owner-Drawn-Element ohne HasString-Flag? (lese gerade die doku)... Dann hast du das Problem, dass der String im Data-Zeiger gespeichert wird und du den Zeiger mit dem SetItemData wieder überschreibst...
    Und dann hast du noch das Problem, dass der Index der Schleife vielleicht gar nix mit dem Index zu tun hat, an dem die Strings landen, die du einfügst, du setzt aber das Itemdata immer für das Element des Schleifenindexes. Wenn die Liste sortiert ist, führt das natürlich zu Problemen.
    AddString liefert den Index zurück...



  • Danke schonmal für deine schnelle Antwort!
    Ich habe mal meine Insert-Funktion überarbeitet:

    HRESULT InitAdapterComboBox(HWND hDlg)
    {
    	ClearComboBox(hDlg, IDC_ADAPTERBOX);
    
    	int AdapterCount = D3DTemp->GetAdapterCount();
    	D3DADAPTER_IDENTIFIER9* Adapters = new D3DADAPTER_IDENTIFIER9[AdapterCount];
    
    	for (int i=0; i < AdapterCount; ++i)
    	{
    		if (FAILED(D3DTemp->GetAdapterIdentifier(i, 0, &Adapters[i])))
    		{
    			MessageBox(NULL, "Adapterinformationen konnten nicht abgefragt werden!", "Fehler", NULL);
    			delete [] Adapters;
    			return E_FAIL;
    		}
    
    		int index = (int) (SendDlgItemMessage(hDlg, IDC_ADAPTERBOX, CB_ADDSTRING, 0, (LPARAM) Adapters[i].Description));
    		SendDlgItemMessage(hDlg, IDC_ADAPTERBOX, CB_SETITEMDATA, index, (LPARAM) i);
    	}
    
    	SendDlgItemMessage(hDlg, IDC_ADAPTERBOX, CB_SETCURSEL, 0, 0);
    
    	delete [] Adapters;
    
    	return S_OK;
    }
    

    Du hattest schon recht mit deinem Bedenken, dass Listenindex und Schleifenindex nichts miteinander zu tun haben köntten, trotzdem war das nicht der Fehler. Auch das free'n von einem nicht alloziertem Objekt war natürlich ziemlich blöd... habe ich übersehen.
    Eine wichtige Frage habe ich jetzt noch: Ist es dann überhaupt noch nötig die Listenelemente zu free'n oder muss das sein und ich sollte dann über malloc() Speicher extra allozieren?



  • Also wenn das Teil nicht Owner-Drawn ist, dann kopiert AddString sich die übergebenen Strings, ansonsten speichert es die übergebenen Zeiger auf die Strings in dem ItemData des Elements.
    Da ich bei Dir vom ersten Fall ausgehe, musst du nix weiter beachten oder tun.


Anmelden zum Antworten