DAMAGE: after normal block(xx) at (0xyy)
-
Hallo,
ich habe ein Programm das die Fehlermeldung DAMAGE: after normal block(xx) at (0xyy) ausgibt.
Beim Debuggen sieht es dann folgendermaßen aus:_free_dbg_lk(void*,int)
_free_dbg_lk(pUserData, nBlockUse)
operator delete(void*)
GiST::WriteNode(GiSTnode*)wobei die Methode WriteNode so implementiert ist:
void GiST::WriteNode(GiSTnode *node) { cout << "gist.cpp writenode-methode\n" << endl; cout << "buffer size " << store->PageSize() << "\n" << endl; char *buf=new char[store->PageSize()]; // make Purify happy memset(buf, 0, store->PageSize()); #ifdef PRINTING_OBJECTS if(debug) { cout << "WRITE PAGE " << node->Path().Page() << ":\n"; node->Print(cout); } #endif node->Pack(buf); store->Write(node->Path().Page(), buf); delete buf; }Beim Befehl delete buf bleibt er mit dem fehler hängen. Allerdings nicht immer, sondern nur wenn der Aufruf von writenode durch diese methode passiert (die ruft writenode zweimal auf - einmal funktioniert beim anderen nicht):
void GiST::Split(GiSTnode **node, const GiSTentry& entry) { int went_left=0, new_root=0; if((*node)->Path().IsRoot()) { new_root=1; (*node)->Path().MakeChild(store->Allocate()); } GiSTnode *node2=(*node)->PickSplit(); node2->Path().MakeSibling(store->Allocate()); GiSTentry *e=(*node)->SearchPtr(entry.Ptr()); if(e!=NULL) { went_left=1; delete e; } node2->SetSibling((*node)->Sibling()); (*node)->SetSibling(node2->Path().Page()); WriteNode(*node); //dieses writeNode wird noch korrekt ausgeführt WriteNode(node2); //dieses nicht mehr GiSTentry *e1=(*node)->Union(); GiSTentry *e2=node2->Union(); e1->SetPtr((*node)->Path().Page()); e2->SetPtr(node2->Path().Page()); // Create new root if root is being split if (new_root) { GiSTnode *root=NewNode(this); root->SetLevel((*node)->Level()+1); root->InsertBefore(*e1, 0); root->InsertBefore(*e2, 1); root->Path().MakeRoot(); WriteNode(root); delete root; } else { // Insert entry for N' in parent GiSTpath parent_path=(*node)->Path(); parent_path.MakeParent(); GiSTnode *parent=ReadNode(parent_path); // Find the entry for N in parent GiSTentry *e=parent->SearchPtr((*node)->Path().Page()); assert(e!=NULL); // Insert the new entry right after it int pos=e->Position(); parent->DeleteEntry(pos); parent->InsertBefore(*e1, pos); parent->InsertBefore(*e2, pos+1); delete e; if(!parent->IsOverFull(*store)) WriteNode(parent); else { Split(&parent, went_left? *e1: *e2); GiSTpage page=(*node)->Path().Page(); (*node)->Path()=parent->Path(); (*node)->Path().MakeChild(page); page=node2->Path().Page(); node2->Path()=(*node)->Path(); node2->Path().MakeSibling(page); } delete parent; } if(!went_left) { delete *node; *node=node2; } else delete node2; delete e1; delete e2; }Ich habe echt keine Ahnung mehr woran das liegt. Habe diverses in Google gefunden, aber geholfen hat nichts. Irgendwas mit dem local Heap geht wohl nicht.
Gruß Simpson84
-
Boar... Also nicht nur, dass die Fkt. viel zu lang ist, ich seh auch nicht durch, wo dort ein Objekt wem gehört - also wer es zerstören darf/muss/sollte und wer eben nicht... (und dort wird der fehler auch liegen)
allein schon das ständige (*node)-> ist sehr eklig anzusehen

Splitte die Fkt doch mal in paar Unterfkt. auf, dann sieht man da vll auch noch durch...
bb
-
Du schreibst irgendwo in Speicher, der dir nicht gehört. Dass passiert meistens wenn man irgendwas mit new[] gefrickelt hat statt Container zu benutzen, und mehr in den Speicherbereich reingeschrieben hat als reinpasst. Beim delete merkt die Runtime das und bringt diese "damage after normal block"-Fehler.
Die genaue Stelle ist oft nicht offensichtlich. Die Kristallkugel sagt, dass du dirstore->Write(node->Path().Page(), buf);mal genauer anschauen sollst.
-
Meine Verteidigung zu der sehr langen Funktion ist, dass ich den Code nicht selber geschrieben habe, sondern einfach nur verwenden möchte. Ich habe auch nicht besonders viel C++ Erfahrung, da ich bis jetzt immer alles in Java implementiert habe. Dort muss man sich ja auch nicht mit der Speicherfreigabe beschäftigen.
Der Aufruf store->Write(node->Path().Page(), buf) führt hier hin.void MTfile::Write(GiSTpage page, const char *buf) { if(IsOpen()) { lseek(fileHandle, page*PageSize(), SEEK_SET); write(fileHandle, buf, PageSize()); IOwrite++; } }Wenn ich die write-Methode hier richtig interpretiere, dann wird in fileHandle der Inhalt von buf hineingeschrieben, oder? Dann kann hier buf nicht übergelaufen sein. Auch der zweite Aufruf node->Pack(buf), in dem der buf eine Rolle spielt macht für mich den Eindruck, als würde buf dabei nicht verändert.
void GiSTnode::Pack(char *page) const { // Pack the header GiSTheader *h=(GiSTheader *) page; h->level=Level(); h->numEntries=NumEntries(); h->sibling=Sibling(); int fixlen=FixedLength(); GiSTlte *ltable=(GiSTlte *)(page+tree->Store()->PageSize()); GiSTlte ltptr=GIST_PAGE_HEADER_SIZE; for(int i=0; i<numEntries; i++) { GiSTcompressedEntry compressedEntry=(*this)[i]->Compress(); if(fixlen) assert(fixlen==compressedEntry.keyLen); // Copy the entry onto the page if(compressedEntry.keyLen>0) memcpy(page+ltptr, compressedEntry.key, compressedEntry.keyLen); memcpy(page+ltptr+compressedEntry.keyLen, &compressedEntry.ptr, sizeof(GiSTpage)); // Be tidy if(compressedEntry.key) delete compressedEntry.key; // Enter a pointer to the entry in the line table if(!fixlen) *--ltable=ltptr; ltptr+=compressedEntry.keyLen+sizeof(GiSTpage); } // Store extra line table entry so we know last entry's length *--ltable=ltptr; }Für mich sieht das also so aus, als wird buf in GiST::WriteNode erstellt, dann passiert nicht mehr viel mit ihm und dann wird er dort wieder gelöscht.
-
Simpson84 schrieb:
Meine Verteidigung zu der sehr langen Funktion ist, dass ich den Code nicht selber geschrieben habe, sondern einfach nur verwenden möchte.
Das ist keine Entschuldigung
Man sollte keinen Code verwenden, den man nicht versteht.
Wenn man ihn aber versteht, gibts keine Entschuldigung, ihn nicht etwas übersichtlicher zu machen (d.h. in kleinere Funktionen zu zerlegen)
-
Ich habe in den Sourcecode mal mehrere assert(_CrtCheckMemory()); eingefügt und dabei crashed das ganze in der Pack-Methode direkt nach
// Copy the entry onto the page if(compressedEntry.keyLen>0) memcpy(page+ltptr, compressedEntry.key, compressedEntry.keyLen);Sieht jemand die Ursache dafür?
-
Ein Debugger könnte dir sicher besser weiterhelfen.
-
char *buf=new char[store->PageSize()]; //... delete[] buf; // <-- statt delete buf;
-
So ein einfacher Fehler und keiner sieht ihn ^^
Ich hab ihn auch nicht gesehen.
gw,
seldon
-
_))) schrieb:
So ein einfacher Fehler und keiner sieht ihn ^^
Ich hab ihn auch nicht gesehen.
gw,
seldondacht ich mir auch... -.-
-
Oh ja, da lag ich wohl voll daneben. Das wusste ich gar nicht, dass so auch der Fehler kommen kann.
-
Besten Dank!
Das war mir noch gar nicht aufgefallen. Das alleine war zwar noch nicht die Lösung, da auch noch inhaltlich im Programm was schief lief.