Seite 1 von 1

(Re)AllocateMemory()-Problem - brauche dringend Hilfe - Bug?

Verfasst: 17.06.2012 09:30
von Toshy
Hallo Leute,
ich arbeite an sich schon lange und oft mit Pointern, an sich nie ein Problem, aber nun kampfe ich hier seit "Wochen" (!!!) ständig mit einem Problem an meinem Code. Irgendwie Läuft es anders als es soll, das passiert ja oft, aber ich habe keine Fehler im Code gefunden. Na ja, keinen der sich auf das hier bezieht.

Ich muß einfach Scheuklappen vor den Augen haben, erklärt mir mal was ich falsch mache, oder ob PB irgend wie anderes reagiert als ich es erwarte. Das muß ja kein Bug sein, nur das ich einfach was übersehe.

Ich habe mich echt über sehr lange Zeit an das Problem rangekämpft. Da das Problem ständig einen Speicherfehler auslöst und damit die Debuggeranzeige weg geht, hat das noch länger gedauert.

Problem:
Ich erstelle einen Speicherbereich. Was hinter dem Speicherbereich steht ist für mich ja an sich uninteressasnt, da sollte ich ja eh nicht darauf zugreifen. Aber durch das testen bin ich darauf gekommen, das ein paar Bytes hinter meinem allokierten Speicher ein Wert steht, immer Wert "11".
An sich geht mich nichts an, was da steht. Nur jetzt reallokiere ich den Speicher. Dann bekomme ich (eventuell) ein neuen Pointer. Unabhängig davon, sollte der Speicherbereich vergrößert sein. Klappt auch. ABER JETZT:
Der Reallokierte Speicher sollte den Inhalt des alten Speichers beinhalten und den zusätzlichen Speicher mit Nullen überschreiben. Aber anstatt dessen, steht der Wert 11 jetzt innerhalb meines allokierten Speichers. Das kann ja nur krachen.
Was mache ich falsch, oder hat da PB glatt einen übersehenen Bug?

Code: Alles auswählen

Structure struct_NetID
  *OutgoingDataBuffer
EndStructure

Structure struct_NetIDOutgoingDataBuffer_PartManagement
  *EventID.struct_NetworkSendEventID
  NetworkSendEventMode.b 
  SuccessfullySend.i
  Size.i
EndStructure

*NetID.struct_NetID = AllocateMemory(SizeOf(struct_NetID))
*NetID\OutgoingDataBuffer = AllocateMemory(2)
  Debug("+5MemorySize(*NetID\OutgoingDataBuffer) = " + Str(MemorySize(*NetID\OutgoingDataBuffer)) + " -  peekl(*NetID\OutgoingDataBuffer+5)" + Str(PeekL(*NetID\OutgoingDataBuffer+5)))
*NetID\OutgoingDataBuffer = ReAllocateMemory(*NetID\OutgoingDataBuffer,17) 
Debug("+5MemorySize(*NetID\OutgoingDataBuffer) = " + Str(MemorySize(*NetID\OutgoingDataBuffer)) + " -  peekl(*NetID\OutgoingDataBuffer+5)" + Str(PeekL(*NetID\OutgoingDataBuffer+5)))  
  
  Delay(20000)
Debugger-Ausgabe
[09:17:40] +5MemorySize(*NetID\OutgoingDataBuffer) = 2 - peekl(*NetID\OutgoingDataBuffer+5)11
[09:17:40] +5MemorySize(*NetID\OutgoingDataBuffer) = 17 - peekl(*NetID\OutgoingDataBuffer+5)11
Getestet unter Windows XP, PB 4.60 und 4.61

Nachtrag:

Code: Alles auswählen

*pointer = AllocateMemory(2)
  Debug("*pointer = " + Str(*pointer ) + " - *pointerSize = " + Str(MemorySize(*pointer)) + " -  PeekL(*pointer+5)" + Str(PeekL(*pointer+5)))
*pointer = ReAllocateMemory(*pointer,17)
Debug("*pointer = " + Str(*pointer ) + " - *pointerSize = " + Str(MemorySize(*pointer)) + " -  PeekL(*pointer+5)" + Str(PeekL(*pointer+5)))
[09:28:50] *pointer = 31858324 - *pointerSize = 2 - PeekL(*pointer+5)11
[09:28:50] *pointer = 31858324 - *pointerSize = 17 - PeekL(*pointer+5)11
2. Nachtrag.
Unter Purebasic Version 4.00 gibt es kein Problem. Da läuft alles korrekt. Ist also wohl ein Bug.
Könntet ihr vielleicht die PB Versionen zwischen PB 4.00 und 4.60 (die beiden nicht) runterladen und schauen, ab welcher Version der Bug auf tritt. Ich kann das nicht machen, DSL ist seit zwei Wochen weg und dauert noch einige Wochen bis umgeschaltet wird. Und da wir hier mit 4 Rechnern nun am Handynetz hängen (nur 5 kbyte/sek) dauert ein zwei Tage alle Versionen zu laden, da die anderen REchner auch im netz sind würde s noch länger dauern.
Die Fehlerversion sollte schnell rausgefunden werden, damit wir Fred das schnell sagen können und er vielleicht ein Zwischenupdate raus gibt. Ein Fehler in der Speicherverwaltung ist ja schließlich ganz übel.
Und sicher nicht nur, weil ich seit 3 Wochen meine Threads sinnlos auf den Kopf gestellt habe.
Heiliger Himmel, bin ich frustriert und erleichtert zu gleich.

Re: (Re)AllocateMemory()-Problem - brauche dringend Hilfe -

Verfasst: 17.06.2012 10:09
von STARGÅTE
Der Bereich vor und hinter einem Speicherblock gehört zum Memory Heap
Ein Thema dazu gibt es schon von mir: AllocateMemory - Interessantes Hintergrundwissen

Ich kann jedoch deine Angaben nicht bestätigen, bei mir steht "irgendwas" dahinter.
In einem Fall zB:
*pointer = 4071056 - *pointerSize = 2 - PeekL(*pointer+5)754990593
*pointer = 4071056 - *pointerSize = 17 - PeekL(*pointer+5)0
Auch das der Speicher, der hinzugefügt wurde nicht leer ist, kann ich nicht bestätigen, wie du an der 0 siehst.

Ich vermute mal, du hast an einer anderen Stelle einen illegalen Speicherzugriff, den du dort u.u. nicht merkst, aber eine heap corruption hervorruf.
Bitte verwende den Purifier am besten mit PurifierGranularity(1,1,1,1).
So kannst du genau sehen, wo es zu illegalen Speicherzugriffen kommt.

Re: (Re)AllocateMemory()-Problem - brauche dringend Hilfe -

Verfasst: 17.06.2012 10:42
von Toshy
Ja, es muß nicht unbedingt "11" sein, aber auf jeden Fall steht da normal was hinter.
Ich habe noch einige alte Versionen gefunden, PB 4.61,4.60,4.51 lösen exakt den selben Fehler und Wert aus. PB-Versionen 4.20 und davor nicht. dazuwischen habe ich keine Versionen gefunden.

Das heißt, es muß an PB liegen. Ich habe auch nicht an anderer stelle einen illegalen Zugriff, da ich gar keinen anderen Code ausführe.
Mittlerweile ist es so nachvolziehbar, das ich nur genau diese 4 Zeilen code ausführen muß.
Der Purifier hat also keinen Sinn.
PurifierGranularity habe ich noch nie genutzt, aber ich glaube das kann man ja auch mit den Schiebereglern einstellen. Da ich aber noch nie eine Meldung erhalten habe weiß ich nicht mal ob der Purifier funktioniert.

ach ja, 32bit-windows xp, nicht 64. selbes problem unter linux in der virtualbox.

Da man das interne Speichermanagment natürlich nicht kennt, kann es gut sein, daß dies Problem nicht immer oder bei jedem Aufritt. Aber das dies nicht an meinem code liegen kann ist klar. Sind ja nur 4 Zeilen und wie gesagt, je nach PB-Version tritt es auf oder nicht.

Re: (Re)AllocateMemory()-Problem - brauche dringend Hilfe -

Verfasst: 17.06.2012 10:47
von ts-soft
Mach den Purifier aus, wenn Du den nicht verstehst :wink:
Die 11 sind die Testbytes, die eigentlich beim reallokieren entfernt werden müssten,
in realen Programmen macht dies aber keine Probleme.

Also lediglich ein Bug oder Einschränkung im Purifier!

Re: (Re)AllocateMemory()-Problem - brauche dringend Hilfe -

Verfasst: 17.06.2012 11:04
von Toshy
Na ja, der Purifier an sich ist ja sinnvoll. Nur meldet er bei mir nichts.
Ich hatte jetzt ca. 2000 Zeilen Code aus dem Kopf erstellt ohne es einmal zu kompelieren. Außer ein paar reinen Tippfehlern oder ein Mutexfehler in bezug auf Listboxen habe ich bei den vielen Pointerzugriffen wohl einfach keine Fehler gemacht.
Speicherfehler unterlaufen mir extremst selten. Liegt wohl hauptsächlich daran, das ich erstens recht gut überlege wie die *Pointer "berechnet" werden und zweitens, das ich einfach beim Aufruf meiner Funktionen immer überprüft wird, daß die größenangaben eingepflegt werden bzw. bei falschen werten abgewiesen werden.
Ein schreiben außerhalb meines Speichers ist mir daher bisher nicht vorgekommen. Einzig, das ich mal Pointer NULL übergebe kommt in der Entwicklungsphase vor.
in realen Programmen macht dies aber keine Probleme.
Wie ist das denn nun gemeint? In realten Programmen darf es solche Probleme ja nicht geben. Und den Dubugger muß ich ja benutzen. Wie schaltet man den Purefier ab? PurifierGranularity(0,0,0,0) etwa? Aber was ist dann mit dem Debugger, gibt der dann noch alle Speicherfehler aus? Also wenn es doch mal eine ungültige *Pointerzuweisung gibt? Schreibfehler die solche Probleme auslösen kommen ja doch mal vor (zwei ähnliche LIstenamen und man wählt die falsche Liste).

Ich will mir das aufinden der Fehler ja nicht noch schwerer machen.

Aber wenn ich PurifierGranularity(0,0,0,0) nutze (was ich ja an sich gar nicht so sinnvoll bei vielen Speicherbearbeitungen finde), dann habe ich auch keinen Fehler mehr und ählniche *Pointerwerte wie du. Ok, bei einem einzigen Test bisher.

Re: (Re)AllocateMemory()-Problem - brauche dringend Hilfe -

Verfasst: 17.06.2012 11:24
von STARGÅTE
Die "normalen" IMAs werden weiterhin vom Debugger gemeldet.
Der Purifier ist nur dafür da, diese IMAs vorzeitig zu verhindern, indem er ggf. illegale Speicher-Schreib-Funktionen meldet.

Das mit der 11 kann ich nun auch bestätigen, aber eben mit Purifier.
Das dieser "Bug" früher nicht da war, liegt daran, dass es früher kein Purifier gab ^^

Purifier abschalten kannst du einfach im Compiler Menü, unter "Debugger einschalten".

Re: (Re)AllocateMemory()-Problem - brauche dringend Hilfe -

Verfasst: 17.06.2012 11:35
von ts-soft
Ich weiß jetzt nicht, ob Freak das fixen kann, weil das halte ich technisch für sehr schwer umsetzbar, aber hierzu kann nur er
genauere sagen.

Als workaround einfach wenn der Debugger an ist, selber den restspeicher mit Fillmemory bereinigen.
Der Compiler wird dies deshalb nicht machen, weil der weiß nichts vom purifier und debugger, weiß aber,
dieser neuallokierte speicher ist leer, da er bestimmt vorher nicht nur 2 Bytes allokiert hat, sondern mit
sicherheit eine sinnvollere grösse, nur nicht bereitgestellt, weil nicht angefordert. Es würde ja extra
Zeit kosten, diesen eigentlich genullten Speicher zu nullen, und dieses in der fertigen exe und nur
weil da beim debugger irgendwelche cookies vom purifier gesetzt wurden.

Egal, versteht sowieso keiner, also WorkAround:

Code: Alles auswählen

*pointer = AllocateMemory(2)
  Debug("*pointer = " + Str(*pointer ) + " - *pointerSize = " + Str(MemorySize(*pointer)) + " -  PeekL(*pointer+5)" + Str(PeekL(*pointer+5)))
*pointer = ReAllocateMemory(*pointer,17)
CompilerIf #PB_Compiler_Debugger
  FillMemory(*pointer + 2, 15)
CompilerEndIf
Debug("*pointer = " + Str(*pointer ) + " - *pointerSize = " + Str(MemorySize(*pointer)) + " -  PeekL(*pointer+5)" + Str(PeekL(*pointer+5)))
// edit
hier ein besser anzuwendendes WorkAround:

Code: Alles auswählen

CompilerIf #PB_Compiler_Debugger
Procedure MyReAllocateMemory(Memory, Size)
  Protected oldsize = MemorySize(Memory)
  Protected result = ReAllocateMemory(Memory, Size)
  If Size > oldsize
    FillMemory(Memory + oldsize, Size - oldsize)
  EndIf
  ProcedureReturn result
EndProcedure
CompilerElse
Macro MyReAllocateMemory(Memory, Size)
  ReAllocateMemory(Memory, Size)
EndMacro
CompilerEndIf

*pointer = AllocateMemory(2)
Debug("*pointer = " + Str(*pointer ) + " - *pointerSize = " + Str(MemorySize(*pointer)) + " -  PeekL(*pointer+5)" + Str(PeekL(*pointer+5)))
*pointer = MyReAllocateMemory(*pointer,17)
Debug("*pointer = " + Str(*pointer ) + " - *pointerSize = " + Str(MemorySize(*pointer)) + " -  PeekL(*pointer+5)" + Str(PeekL(*pointer+5)))

Re: (Re)AllocateMemory()-Problem - brauche dringend Hilfe -

Verfasst: 17.06.2012 15:59
von Toshy
@STARGATE:
Purifier abschalten kannst du einfach im Compiler Menü, unter "Debugger einschalten".
Danke.
Aber mir ist gerade jetzt eingefallen, beim Debuggen mache ich am bessten einen einfachen workaround.
Ich nutze FillMemory() und überschreibe den Teil selber. Da ich ich ein Macro mit Fehlerroutine für alle reallocatememory() nutze ist das ja gar kein Problem.
Dann kann mir der Purifer wenigstens doch noch helfen mögliche Fehler aufzudecken.

Ich habe jetzt zwar viel Zeit verloren, aber wenigstens ist der größte Teil vom Frust weg.

@ts-soft:
Deinen Beitrag hatte ich noch gar nicht gelesen...Fillmemory() hehe, selbe Gedanke. Danke.
Aber warum sollte man das nicht fixen können? Das ist doch eine Basisfunktion die wichtig ist und ohne Debugger doch auch normal läuft. hmm. Na ja, das ist ja nicht meine Sache. Aber ein paar Byte die vergessen wurden zu überschreiben, das wird er wohl hoffenlich hin bekommen. Wie der Debugger usw. das Programm überwacht weiß ich nicht. Aber wirklicher verstanden habe ich wirklich etwas nicht. 2 Byte sind allokiert, dann reallokieren. das wird sicher die windowsapi zu aufgerufen. dann wie du schon sagst, sollte auch diese funktion ja an sich den speicher mit nullen füllen bzw. null sein. warum dann NACH den neuallokieren noch der Wert drinn steht oder eventuell sogar wieder gesetzt wird weiß und verstehe ich nicht. Aber wird sich demnächst zeigen was draus wird. Solange es nur beim debuggen ist, ... Workaround wie du sagst. Und wie ich oben schon schrieb muß ich nicht mal im Hauptcode meiner ganzen Dateien rumpfuschen. zum Glück habe ich solche Basicmakros in einer Datei für alle Codes ausgelagert. :-)

Beim testen bin ich nur verrückt geworden. erstmal nach längerem coden code ausgeführt... mehrere Thread die quasi nur alles abarbeiten, wenn auch alle laufen und dann so ein fehler. debuggerausgabe verschwindet dann ja ständig (also über zwischenablage) und suchen suchen suchen. ich bin echt verrückt geworden. vor allem wird anfangs ja nicht immer mit 2 bytes allokiert. ich bin echt fast wahnsinnig geworden.
Dann hatte ich die vermeintliche Stelle gefunden, aber gedacht, das einfach ein anderer Thread an der sTelle was auslöst. War ja unlogisch das reallocate den Fehler auslöst. Vor allem in meinen ersten Testcodes waren es dann ja nie 2 byte. Ihr hättet mich mal sehen sollen, als mir klar wurde, das es von PB aus geschieht. lach. So fluchend und kurz schreiend sieht man mich wohl nur alle paar Jahre. hehe

Danke euch.

Toshy

Re: (Re)AllocateMemory()-Problem - brauche dringend Hilfe -

Verfasst: 17.06.2012 16:24
von ts-soft
Toshy hat geschrieben:2 Byte sind allokiert, dann reallokieren. das wird sicher die windowsapi zu aufgerufen
Das glaub ich eher nicht :wink: . Der Compiler wird doch nicht für jede Variable je nach Typ 1, 2, 4 oder 8 Bytes allokieren,
genausowenig wenn Du so wenig speicher anforderst. Da wird schon von Hause aus ein grösserer Pool bereit stehen,
der für den Compiler genullt ist, aber der Purifier hat da heimlich reingekritzelt :mrgreen:
Wann soll der Purifier sein gekritzel wieder entfernen? Vor dem reallokieren, ist ihm dies nicht bekannt und danach
wird es etwas schwierig.
Debugger arbeitet selbständig und nicht unbedingt mit dem Compiler zusammen, was auch vollkommen normal ist.

Gruß
Thomas

Re: (Re)AllocateMemory()-Problem - brauche dringend Hilfe -

Verfasst: 17.06.2012 19:39
von STARGÅTE
Also hinter einem reservierten Speicher steht, wenn der Purifier an ist immer:
"bad food", in HEX: 0BAD F00D, in Bytes: 11, 173, 240, 13

Das Problem ist nun, wenn du irgendeine Größe an Speicher reservierst, wird in wirklichkeit etwas mehr reserviert, nämlich für den Purifier.
Das heißt, es werden in deinem Beispiel nicht 2 sonden vermutlich 2+8=10 Bytes reserviert, denn auch der Purifier darf ja sein "schlechtes Essen" nicht illegal irgendwo hinschreiben.
Pure Basic weiß das mit der Größe und zeigt bei MemorySize trotzdem nur 2 Byte an.
Wenn nun der Speicher erweitert wird, wird nun eine WIN-API aufgerufen, die nun aber die (2+8) Byte auf (17+8) Byte erweitert.
Das heißt, für die Win-API ist das "bad food" teil des reservierten Speichers, somit wird es von dieser auch nicht gelöscht.

Das heißt, wenn dann muss PureBasic, wenn es weiß, dass die letzten 8 Byte immer von Purifier sind, diese selbst löschen.
Da MemorySize richtig arbeitet, sollte es für ReAllocate auch funktionieren, dass eine "alternative" Funktion aufgerufen wird.