realloc
-
Hallo.
Die schöne realloc funktion ist mir grade ziemlich am auf die nerven gehen. In meinem Programm wird eine Funktion benötigt, die einen Teil eines Strings entfert. das ganze sieht ungefähr so aus:LRESULT DlgText::CutString(TCHAR **pFrom, TCHAR *pTo) { _w64 int ntemp = lstrlen(pTo); _w64 int ntemp2 = (pTo - *pFrom); _w64 int nPlace = *pFrom - m_DataPointer; TCHAR *tempstr = (TCHAR*) malloc(ntemp * sizeof(TCHAR)); lstrcpy(tempstr, pTo); lstrcpyn(*pFrom, tempstr, ntemp* sizeof(TCHAR)); RtlZeroMemory(*pFrom + (ntemp* sizeof(TCHAR)),ntemp2); m_nDataLen -= ntemp2; m_DataPointer = (TCHAR*) realloc(m_DataPointer, m_nDataLen); free(tempstr); *pFrom = m_DataPointer + nPlace; return DT_OK; }
m_DataPointer ist die Zeichenkette (der klasse)
die beiden Parameter sind innerhalb der Zeichenkette liegende Pointer, die auf die Stellen zeigen, von wo bis wo entfernt werden soll. m_nDataLen ist die Länge der Zeichenkette (in Bytes).Da ja etwas aus der Zeichenkette rausgeschnitten wird, soll auch der reservierte Speicher verkleinert werden. Dazu nutze ich realloc().
Wenn beim Debuggen die Zeile mit realloc erreicht wird, bzw ausgeführt wird, krieg ich erstmal sowas angezeigt:
Windows has triggered a breakpoint in DlgText.exe.
This may be due to a corruption of the heap, and indicates a bug in DlgText.exe or any of the DLLs it has loaded.
The output window may have more diagnostic information
wenn ich dann auf "continue" drücke, gibts ne weitere Fehlermeldung:
Debug Assertion Failed!
Program: d:\prog lernen\DlgText\DlgText\Debug\DlgText.exe
File: dbgheap.c
Line: 692Expression: _CrtIsValidHeapPointer(pUserData)
For information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts.(Press Retry to debug the application)
Die Fehlermeldungen sind zwar schön aber net wirklich was für jemanden mit meiner Programmiererfahrung
.
Wieso scheitert realloc()?achso - free(tempstr); resultiert auch in einem fehler. wieso sich das nicht freigeben lässt versteh ich überhauptnicht...
Joa: Hilfe!!!!
-
Grrrrrrrrrr. Sonntag...
-
Un Dienstag immer noch nix...
-
krieg ich nich ma ne anmerkung, dass ich das problem falschh dargestellt habe oder sowas???
-
Du holst zu wenig Speicher für tempstr, die Nullterminierung passt da nicht mehr mit rein. Das gleiche gilt womöglich auch für m_DataPointer, das kommt drauf an, ob m_nDataLen die Länge einschließlich Nullterminierung beinhaltet.
Das Problem kann aber auch sein, dass du dir an ganz anderer Stelle den Heap zerschießt.
-
Danke für die Antwort.
Hab nun ein TCHAR mehr reserviert. Hab dasselbe bei M_DataPointer gemacht (m_nDataLen vergrößert). Fehlermeldungen kommen trotzdem.
Hab versucht, m_dataPointer mit der alten Größe zu "realloc"cen. Er meint trotzdem irgendwas stimmt nicht mit dem Heap. Ich kenn mich mit der Sache heap net so wirklich aus, das ist das Problem. Welche stellen können denn dafür verantwortlich sein, dass der Heap kaputt geht?
-
Azrael, il Meraz schrieb:
Welche stellen können denn dafür verantwortlich sein, dass der Heap kaputt geht?
Alle, an denen du in Speicher schreibst, der mit malloc oder verwandten Funktionen geholt wurde.
-
Woah - hab grad nur die zeile mit ZeroMemory ausgeklammert (na gut - un ein try/catch eingebaut):
LRESULT DlgText::CutString(TCHAR **pFrom, TCHAR *pTo) { try { _w64 int ntemp = lstrlen(pTo); _w64 int ntemp2 = (pTo - *pFrom); _w64 int nPlace = *pFrom - m_DataPointer; TCHAR *tempstr = (TCHAR*) malloc((ntemp+1) * sizeof(TCHAR)); lstrcpy(tempstr, pTo); lstrcat(tempstr, TEXT("\0")); lstrcpyn(*pFrom, tempstr, ntemp* sizeof(TCHAR)); /*RtlZeroMemory(*pFrom + (ntemp* sizeof(TCHAR)),ntemp2);*/ m_nDataLen -= ntemp2; m_DataPointer = (TCHAR*) realloc(m_DataPointer, m_nDataLen); free(tempstr); *pFrom = m_DataPointer + nPlace; } catch(...) { return DT_MAE; } return DT_OK; }
hmmm das geht jetzt. aber irgendwie bin ich mit dem ergebnis nicht zufrieden - das muss doch richtig sein - das was ich bei ZeroMemory löschen will Oo. Nach dem eingefügten Teil sollen Nullen in die Zeichenkette! Ist zwar glaub ich nicht zwingend notwendig, aber ich kann nicht erkennen wo mein Fehler war
-
Der Faktor sizeof(TCHAR) ist das Problem. Den darfst du beim ersten Parameter von RtlZeroMemory nicht benutzen, weil Addition bei Zeigern die Größe des Typen bereits berücksichtigt (Stichwort Zeigerarithmetik). Allerdings brauchst du den Faktor beim zweiten Parameter, weil dasselbe bei der Berechnung von ntemp2 passiert: Das Ergebnis ist in der "Einheit" sizeof(TCHAR).
-
oha. ausprobiert. es klappt Oo.
das ist mir nun nicht ganz klar - ntemp und ntemp2 sind ja beides _w64 int werte
der erste berechnet sich aber aus lstrlen(pTo), also muss er doch die Anzahl der Buchstaben enthalten, oder?
und das zweite ist eine Subtaktion von Pointer also muss er doch die anzahl der Bytes dazwischen enthalten.
wenn der erste nun als offset verwendet wird, setzt ZeroMemory doch Bytes voraus? Un ein lstrlen liefert doch anzahl der Buchstaben?
und das zweite sind doch schon bytes, wieso muss hier mit sizeof(TCHAR) multipliziert werden? Oo Oo Oo
-
Azrael, il Meraz schrieb:
und das zweite ist eine Subtaktion von Pointer also muss er doch die anzahl der Bytes dazwischen enthalten.
Nein. Genau das meinte ich. Informier dich mal über Zeigerarithmetik. Wenn du bei Zeigern Addition oder Subtraktion benutzt, ist das immer in Vielfachen der Größe des Typen, auf den gezeigt wird.
Das heißt, ntemp2 enthält die Anzahl der TCHARs zwischen pTo und *pFrom. Und wenn du auf *pFrom etwas draufaddierst, wird dabei automatisch die Größe von TCHAR berücksichtigt.
-
Aha!. Danke^^.
Zeigerarithmetik hrhrhrhr. ist sicherlich hilfreich. werd ich machen.Immer wieder schön was neues zu lernen.
Boah... Und sowas einfaches frisst seit paar Wochen mein Hirn. grrrrrrrrrr... muss irgendwas kaputt machen. lol