Nicht auffindbarer Grund für Schutzverletzung. Generierung von Farbtabelle.



  • Hallo

    auch wenn ich eben schon einen Beitrag verfasst habe der ansatzweiße damit zu tun hat (Short in Byte umwandeln) haben die Lösungsideen da nicht zur Lösung meines eigentlichen Problems geholfen.
    Ich nutze aus C# heraus eine C++ DLL die für mich etwas auf den DeviceContext via GDI malt. Diese Funktion nutzt eine Geodaten-Bibliothek GDAL welche mir unter anderem eine Farbtabelle für ein zu ladendes Bild gibt. Diese Farbtabelle will ich nun dem Generieren einer DIBSection zur Anzeige mitgeben.
    An sich klappt alles und die Farben seh ich auch kurz auf dem Bildschirm (und irgendwie klappte das ganze auch schonmal ohne Fehler - also alles lief wie es sollte - abre scheinbar habe ich irgendwas kleines geändert 😞 ) aber danach kommt eine Schutzverletzung, bzw. folgender Fehler:

    Ausnamecode: 0xc0000005
    Ausnahmeadresse: 0x12ca668
    Lesen: 0x00fb0d1c
    

    Dazu folgender Quellcode der relevanten Funktion:

    void CGDALContainer::DrawAllImages(HDC hDC) {
    	if (hDC == NULL) return;
    	int		cCT;
    	int		length	= geoTiffs.size();
    	HDC		hDCMem	= CreateCompatibleDC(hDC);
    	GDALColorTable* ct;
    	HBITMAP hMemBitmap;
    
    	BITMAPINFO bmi;
    	::ZeroMemory(&bmi.bmiHeader, sizeof(BITMAPINFOHEADER));
    	bmi.bmiHeader.biWidth = width;
    	bmi.bmiHeader.biHeight = -(height); //negative indicate top down, not bottom up
    	bmi.bmiHeader.biPlanes = 1;
    	bmi.bmiHeader.biBitCount = 8;
    	bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    	bmi.bmiHeader.biCompression = BI_RGB;
    	bmi.bmiHeader.biSizeImage = bmi.bmiHeader.biWidth * bmi.bmiHeader.biHeight * bmi.bmiHeader.biBitCount / 8;
    
    	for (int i = 0; i<length; i++) {
    		ct = geoTiffs[i]->getColorTable();
    		cCT = ct->GetColorEntryCount();
    		bmi.bmiHeader.biClrUsed = bmi.bmiHeader.biClrImportant = cCT;
    		FILE * pFile = _wfopen(L"PDAShpTool_ErrorLog.log",L"a");
    		for (int j = 0; j<cCT; j++) {
    			fwprintf(pFile, L"j: %d ", j);
    
    			const GDALColorEntry * entry = ct->GetColorEntry(j);
    			fwprintf(pFile, L"cT: %d ", cCT);
    			bmi.bmiColors[j].rgbRed = static_cast<unsigned char>(entry->c1);
    			fwprintf(pFile, L"r: %d (%d) ", bmi.bmiColors[j].rgbRed, entry->c1);
    			bmi.bmiColors[j].rgbGreen = static_cast<unsigned char>(entry->c2);
    			fwprintf(pFile, L"g: %d (%d) ", bmi.bmiColors[j].rgbGreen, entry->c2);
    			bmi.bmiColors[j].rgbBlue = static_cast<unsigned char>(entry->c3);
    			fwprintf(pFile, L"b: %d (%d) \n", bmi.bmiColors[j].rgbBlue, entry->c3);
    			bmi.bmiColors[j].rgbReserved = 0;
    		}
    		fwprintf(pFile, L"finished\n");
    		fclose(pFile);
    		hMemBitmap = ::CreateDIBSection(hDCMem, &bmi, DIB_RGB_COLORS, (void **)&pafScanline, NULL, 0);
    		memcpy_s(this->pafScanline, this->bufferSize, geoTiffs[i]->getBytes(), bufferSize);
    	}
    
    	SelectObject(hDCMem, hMemBitmap);
    
    	BitBlt(hDC, 0, 0, width, height, hDCMem, 0, 0, SRCCOPY);
    
    	DeleteObject(hMemBitmap);
    
    	DeleteDC(hDCMem);
    }
    

    Anhand des Bildschrims und der genierten Datei sehe ich dass das Bauen der Farbtabelle, sowie das Generieren der DIBSection funktioniert.
    Der Fehler kommt aber nicht wenn ich das Schreiben in die Farbtabelle (also die konvertierten Farben in "bmi" schreibe) weglasse. Es reicht die Zuweisugnszeilen wie "bmi.bmiColors[j].rgbRed = ..." auszukommentieren.

    Seltsammerweise geht es auch nicht wenn ich zB folgendes in der Schleife mache:

    bmi.bmiColors[j].rgbRed = j*100; // static_cast<BYTE>(entry->c1);
    bmi.bmiColors[j]->rgbGreen = j*100; // (BYTE)(entry->c2);
    bmi.bmiColors[j]->rgbBlue = j*100; //(BYTE) (entry->c3);
    bmi.bmiColors[j]->rgbReserved = 0;
    

    Es sollten ja eigentlich Schwarz und ein Grau-Ton kommen - aber der Fehler ist auch da... Da muss irgend ein elementarer Fehler da sein

    Falls es relevant ist, hier die Ausgabe der Test-Datei:

    j: 0 cT: 2 r: 128 (128) g: 255 (255) b: 0 (0)
    j: 1 cT: 2 r: 251 (251) g: 13 (13) b: 0 (0)
    finished
    

    Ergo muss der Fehler da irgendwie liegen. Wie gesagt kommt der Fehler erst am Ende der Funktion. Wenn ich zB eine Messagebox am Ende anzeigen lasse, kommt diese noch und danach kommt der Fehler.

    Wie gesagt, die Funktion wird via P/Invoke von C# aufgerufen und ihr wird praktisch der Devicecontext übergeben.

    Da ich noch nicht soo C++ bewandert bin und ich nun nach sehr langem Suchen immernoch nicht nicht weiter gekommen bin, bitte ich um eure Hilfe.

    Vielen Dank
    Tom



  • ich denk mal, du überschreibst da einfach die arraygrenzen von bmiColors. Wie viele Elemente passen denn da rein, und wie groß ist cCT? Die fkt stürzt dann am ende ab. wo sie den stack aufräumt, wei lda was drin sthet was da nicht stehen darf.



  • Danek für die Antwort Maxi,

    das erklärt ja zumindest erstmal warum die Funktion am Ende abstürzt und nicht eher.
    Nun, jetzt wo ich nochmal drüber nachdenke hat das Array, ähem, noch gar keine Größe da ich ihr ja vorher auch nix zuweise.
    Das wollte ich eben auch probieren (also es muss ja damit zusammen hängen) nur steht in der Beschreibung der Struktur:

    typedef struct tagBITMAPINFO {
        BITMAPINFOHEADER    bmiHeader;
        RGBQUAD             bmiColors[1];
    } BITMAPINFO, FAR *LPBITMAPINFO, *PBITMAPINFO;
    

    Und da ist die Farbtabelle ja nur 1 Feld lang. Hm - wie vergößere ich das nun?

    Edit:
    Du hattest recht - na klar, woher soll er denn auch den Speicher nehmen...

    BITMAPINFO * bmi;
    bmi = (BITMAPINFO*) malloc(sizeof(BITMAPINFOHEADER) + cCT * sizeof(RGBQUAD));
    

    Damit ging es 🙂

    Nochmals vielen, vielen Dank



  • Sieht nach WinAPI aus.



  • ehr MFC...

    mach doch:

    BITMAPINFO *bmi = new BITMAPINFO[cCT];
    //füllen
    delete[] bmi;
    


  • BorisDieKlinge schrieb:

    mach doch: [...]

    Ne, die Struktur hat ja eine wandelbare Größe, deklariert ist sie mit nur einem RGBQUAD, sind in der Regel aber mehr 🙂



  • Nee das ist schon WinApi - also kein MFC.

    Aber freigeben sollte ich den Speicher vermutlich wirklich noch 😛

    Danke.



  • Dieser Thread wurde von Moderator/in HumeSikkins aus dem Forum C++ in das Forum WinAPI verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.


Anmelden zum Antworten