Fehler bei free in Struct-Arrays
-
Guten Morgen.
Ich bräuchte mal einen Tip, bitte. Es geht um Folgendes: Ich brauche ein Struct, welches aus einem INT und 3 dynamischen Arrays besteht.
Was ich bisher habe:
In der StdAfx.h:#pragma once #pragma pack(push) #pragma pack(1) typedef float *floatCol; typedef struct ssFB { int anz; floatCol X; floatCol Y; floatCol Z; } sFB; typedef sFB *pFB; #pragma pack(pop)Und in meinem \1:
int z; int max=1000; int max2=40; pFB test; test=(pFB) malloc(max * sizeof(pFB)); for (z=0;z < max;z++){ test[z].X=(floatCol) malloc(max2 * sizeof(floatCol)); test[z].Y=(floatCol) malloc(max2 * sizeof(floatCol)); test[z].Z=(floatCol) malloc(max2 * sizeof(floatCol)); } test[991].anz=1; test[992].anz=2; test[993].anz=test[991].anz+test[992].anz; test[1].X[31]=5; test[1].X[32]=7; test[1].X[33]=test[1].X[31]+test[1].X[32]; sprintf(szHello,"%s %d %f","Taag",test[993].anz,test[1].X[33]); for (z=0;z < max;z++){ /*free (test[z].X); free (test[z].Y); free (test[z].Z);*/ } if(NULL != test){ //free(test); }Es "scheint" auch zu klappen, in meinem szHello stehen die richtigen Werte. Allerdings kracht es immer, wenn ich free(irgendwas) aufrufe.
Evtl. Habe ich einen Denkfehler bei der Verwendunng von floatCol? Wäre da ein pointer richtig? Wenn ja, wie muss ich das denn dann machen?
Über Vorschläge/Tipps/Hilfen würde ich mich sehr freuen.
Vielen Dank
-
Wir sind hier im C++ Board - und da würde ich anstelle eines nackten float-Zeigers lieber std::vector<float> verwenden. (wenn du in C schreiben willst, sag Bescheid, dann schicke ich dich eine Etage höher).
Zu deinem Code:
- malloc() sollte man nicht casten
- die Größenangaben, die du an malloc() geschickt hast, sind falsch - du reservierst Platz für 1000 Zeiger und willst dort anschließend 1000 volle struct's reinpacken (letzteres benötigt etwa den vierfachen Platz).
-
Vielen Dank erstmal.
Anscheinend (oder eher ziemlich sicher ;-)) haue ich da die Verwendung von Zeigern und structs und so weiter noch etwas durcheinander.
Ich habe mich schonmal and std:vector versucht, aber es nicht gebacken bekommen. Ist schon was länger her, vielleicht sollte ich einen neuen Versuch unternehmen, das zu verstehen. Würde mich vorübergehend doch jetzt erst mal dazu entscheiden, das mit einem nackten Zeiger zu machen. (Oder erkaufe ich mir das mit Problemen woanders?)
Zu den anderen beiden Punkten Deiner Antwort.
Wenn ich malloc nicht caste, bekomme ich es nicht kompiliert (VC++6). Was habe ich durch das Casten für Nachteile?
Ich verstehe "grob", was Du damit meinst. Aber an welcher Stelle muss ich welchen Unterschied machen, damit ich in meinen 1000 structs nur die jeweils 3 Unterarrays als Zeiger und nicht als komplette Structs initialisiere?
DANKE
-
hvsecpp schrieb:
Vielen Dank erstmal.
Anscheinend (oder eher ziemlich sicher ;-)) haue ich da die Verwendung von Zeigern und structs und so weiter noch etwas durcheinander.
Ich habe mich schonmal and std:vector versucht, aber es nicht gebacken bekommen. Ist schon was länger her, vielleicht sollte ich einen neuen Versuch unternehmen, das zu verstehen. Würde mich vorübergehend doch jetzt erst mal dazu entscheiden, das mit einem nackten Zeiger zu machen. (Oder erkaufe ich mir das mit Problemen woanders?)
durch die Verwendung von nackten Zeigern schaffst du dir schon genug Probleme, durch die Verwendung der C Verwaltungsfunktionen malloc()/free() kommen noch weitere hinzu (C++ hat new[]/delete[]). Ich würde dir empfehlen, auf beides verzichten und stattdessen vectoren verwenden:
typedef vector<float> floatCol; typedef struct ssFB { int anz; floatCol X; floatCol Y; floatCol Z; } sFB; ... int max=1000; int max2=40; vector<sfB> test; test.resize(max); for(int z=0;z<max;++z) { test[z].X.resize(max2); test[z].Y.resize(max2); test[z].Z.resize(max2); }//wobei eigentlich mußt du nur die Elemente vergrößern, die du im weiteren Verlauf auch verwenden willst ... die Verwendung funktioniert wie gehabtZu den anderen beiden Punkten Deiner Antwort.
Wenn ich malloc nicht caste, bekomme ich es nicht kompiliert (VC++6). Was habe ich durch das Casten für Nachteile?
Siehe oben - malloc() solltest du in C++ Programmen erst recht nicht verwenden (und in C hinderst du mit diesem Cast den Compiler an einer brauchbaren Diagnose).
Ich verstehe "grob", was Du damit meinst. Aber an welcher Stelle muss ich welchen Unterschied machen, damit ich in meinen 1000 structs nur die jeweils 3 Unterarrays als Zeiger und nicht als komplette Structs initialisiere?
Nimm vernünftige Klassen - und wenn du wirklich mit Zeigern arbeiten willst, nimm new -
test=new sFB[max];bzw.test[z].X=new float[max2];.
-
So, ich habe mich jetzt da durch gewühlt, und es klappt auch alles.
Ich habe folgendes:
In der StdAfx.h#pragma pack(push) #pragma pack(1) typedef struct ssBGR { unsigned char b; unsigned char g; unsigned char r; unsigned char pad; } sBGR; typedef sBGR *pBGR;In der OnDraw:
CDC hdcNew,hdcMem; HBITMAP hBmp; HBITMAP hBmpMem; pBGR dst, dstLine; BITMAPINFO bi; dst = MyGetDibBits(hdcMem, hBmpMem, x, y); dstLine = dst; // Start timing for (int stepY = 0; stepY < y; stepY++) { for (int stepX = 0; stepX < x; stepX++) { (sFB*) dies=&test[(stepY) * x + stepX+1]; dstLine[stepX].b = dies->b; dstLine[stepX].g = dies->g; dstLine[stepX].r = dies->r; } dstLine = dstLine + x; } // Set the new Bitmap bi.bmiHeader.biSize = sizeof(bi.bmiHeader); bi.bmiHeader.biWidth = x; bi.bmiHeader.biHeight = y; bi.bmiHeader.biPlanes = 1; bi.bmiHeader.biBitCount = 32; bi.bmiHeader.biCompression = BI_RGB; bi.bmiHeader.biSizeImage = x * 4 * y; bi.bmiHeader.biClrUsed = 0; bi.bmiHeader.biClrImportant = 0; bool res=SetDIBits(hdcMem, hBmpMem, 0, y, dst, &bi, DIB_RGB_COLORS); DeleteObject(hBmpMem); // Create the output HDC hdcNew.CreateCompatibleDC(mpdc); hBmp=CreateCompatibleBitmap(mpdc->GetSafeHdc(), x,y); SelectObject(hdcNew, hBmp); // Fill the output HDC with the window background color and BitBlt the rotated bitmap into it BitBlt(hdcNew, 0, 0, x, y, hdcMem, 0, 0, SRCCOPY); DeleteDC(hdcMem); BitBlt(mpdc->GetSafeHdc(), 0, 0, x, y, hdcNew, 0, 0, SRCCOPY);Und als Funktion
pBGR MyGetDibBits(HDC hdcSrc, HBITMAP hBmpSrc, int nx, int ny) { BITMAPINFO bi; BOOL bRes; pBGR buf; bi.bmiHeader.biSize = sizeof(bi.bmiHeader); bi.bmiHeader.biWidth = nx; bi.bmiHeader.biHeight = - ny; bi.bmiHeader.biPlanes = 1; bi.bmiHeader.biBitCount = 32; bi.bmiHeader.biCompression = BI_RGB; bi.bmiHeader.biSizeImage = nx * 4 * ny; bi.bmiHeader.biClrUsed = 0; bi.bmiHeader.biClrImportant = 0; buf = (pBGR) malloc(nx * 4 * ny); bRes = GetDIBits(hdcSrc, hBmpSrc, 0, ny, buf, &bi, DIB_RGB_COLORS); if (!bRes) { free(buf); buf = 0; } return buf; }ok, das ist nicht das ganze Script (und manches habe ich mir auch zusammengesucht), aber ich denke das Wichtigste, um mein Probem zu schildern:
Das hier funktioniert an und für sich super. Ich kann damit ein OCX malen.
NUR kracht das ganze in Vista zusammen.Ich vermute, das liegt an dem letzten noch übrigen malloc?
Ich habe schon versucht, das wegzubekommen, indem ich meine Zeiger in vectoren umgebaut habe, aber da schaffe ich es nicht, etwas angezeigt zu bekommen. Ich denke, der Fehler kommt, wenn ich &dst in die GetDIBits schubse, denn da ist bRes immer false.
Wie könnte ich ohne malloc hier weiterkommen? Oder siehst Du auf Anhieb noch einen Grund, warum das hier in Vista kracht?
Vielen Dank.
-
alter. hier c++. malloc böse. warum ignorierst du was cstoll dir erzählt?
-
Hi.
Ich wills ja nicht ignorieren, sondern ausbauen. Kann das nur Stück für Stück machen, und jetzt ist dieses Stück dran, nur leider weiss ich hier keinen Ansatz.
SORRY.
-
Ersetze doch die pBGR Variablen durch vector<sBGR>. Auch das kannst du in GetDIBits verwenden.
Hier mal als Beispiel MyGetDibBits.std::vector<sBGR> MyGetDibBits(HDC hdcSrc, HBITMAP hBmpSrc, int nx, int ny) { BITMAPINFO bi; BOOL bRes; bi.bmiHeader.biSize = sizeof(bi.bmiHeader); bi.bmiHeader.biWidth = nx; bi.bmiHeader.biHeight = - ny; bi.bmiHeader.biPlanes = 1; bi.bmiHeader.biBitCount = 32; bi.bmiHeader.biCompression = BI_RGB; bi.bmiHeader.biSizeImage = nx * 4 * ny; bi.bmiHeader.biClrUsed = 0; bi.bmiHeader.biClrImportant = 0; std::vector<sBGR> buf(nx * 4 * ny); bRes = GetDIBits(hdcSrc, hBmpSrc, 0, ny, &(buf[0]), &bi, DIB_RGB_COLORS); if (!bRes) buf.clear(); return buf; }
-
Jetzt weiss ich, warum es völlig ausreicht, bei komplizierten Problemen (für mich zumindest kompliziert) bei Euch zu fragen.
Ihr habts einfach drauf ;-))
DANKE
Soweit war ich fast schon gewesen, was mir noch gefehlt hatte, war dieser Parameter:
&(buf[0]),ich hatte es mit
&buf,versucht, und genau da war der Haken...
schüss ...