![]() |
GetMem verursacht Fehler
Da war ich jetzt so stolz auf mich, hab es geschafft dass in OpenAL ein Wavesound abspielt, alles eigens programmiert ohne große Delphierfahrung und jetzt sowas...
GetMem verursacht eine SIGSEGV die ich mir nicht erklären kann. Das Programm funktioniert folgendermaßen: Ich habe eine Klasse, die WAVE-Klasse, die liesst mit einem TFileStream den WAVE-Header. Danach wird, je nach BitRate (8, 16, 24 (> 32)) ein dynamisches Array mit 16 Einträgen erstellt (nennen wir das mal Datenblock). Aus der Datei werden die 16 Einträge in den Datenblock gelesen, und mit Move in ein dyn. Array kopiert. (Für den fall von einer BitRate von 16bits, wie es üblich ist ist es als ein Array of SmallInt mit xxxxxxx Elementen. Also sehr viele. Normalerweise 2-3Millionen). Dann geb ich den Speicher des Datenblocksfrei (setlength(DataBlock16,0)). So und wenn ich danach, ganz unabhängig davon, in einer anderen Klasse (TForm1) mit GetMem speicher allozieren will, gibts einen Fehler. Bis zu 500bytes kann ich mit GetMem holen, danach schlägt es fehl. Kein EOutOfMemory ( ReturnNilIfGrowHeapFails hab ich auf True gesetzt ), kein gar nichts. Ich mach auch nicht mehr.
Delphi-Quellcode:
SIGSEGV. Egal was.
procedure TForm1.Button6Click(Sender: TObject);
var c: ^byte; begin getmem(c, 555); //<- Da tritt der Fehler auf freemem(c); end; Wenn ich den GetMem VOR dem Laden der WaveDatei benutze geht es. Es kann nichts mit der Größe der WAVEDatei zu tun haben. Während getMem bei fast allen meiner WAVEs fehlschlägt (zB bei meiner 30mb Wave) funktioniert es wiederum mit einer 50mb Wave. OutOfMemory ist also fast ausgeschlossen. Ich bin komplett ratlos was das angeht. Ich muss diese Lowlevel Funktionen benutzen damits schnell geht im Programm.. Den Speicher davor zu beanschlagen ist keine Option, das muss danach geschehen. Hat jemand von euch ne Ahnung was das betrifft, oder ähnliche Erfahrung? Liegs an mir oder am FPC? Im Internet hab ich einige Bugbeschreibungen gefunden mit ähnlichem Problem, allerdings immer ohne Antworten oder Lösungsvorschläge... :wall: Gruß, Jan |
Re: GetMem verursacht Fehler
Das hört sich nach einem Speicherleck an, vielleicht überschreibst du irgendwo Speicher. Das äußert sich dann oft an ganz anderen Stellen und zufällig. Warum habe ich
![]() Schreib am besten in deinen Projektquelltext (Projekt --> Quelltext anzeigen) nach dem begin:
Delphi-Quellcode:
(geht erst am Delphi 2006)
ReportMemoryLeaksOnShutdown := True;
Dann kommen beim Beenden ggf. meistens Meldungen bei Fehlern. Zudem kannst du einmal die Bereichsüberprüfung einschalten: Projekt --> Optionen... --> Compiler --> Laufzeitfehler --> Bereichsüberprüfung oder in neuen Versionen: Projekt --> Optionen... --> Delphi-Compiler --> Kompilieren --> Laufzeitfehler --> Bereichsüberprüfung Das deckt in den meisten Fällen auf, wenn du z.B. einen Index größer als der maximale Index in einem dynamischen Arrays benutzt. |
Re: GetMem verursacht Fehler
Hallo,
d.h. dein Wave-Code zerschiesst intern in der Speicherverwaltung etwas, vielleicht bei der ButtonX-Methode des Form1. Warum nimmt hier jeder dynamische arrays ??? OK, OK, sieht schick aus. Aber wenn ich 16 Felder brauche, definiere ich ein array[1..16]. Um den Fehler einzugrenzen: 1. Lass mal testweise das setlength(DataBlock16,0) komplett weg. 2. Kommentier den Wave-Code komplett aus und dann stückweise wieder "rein" Heiko |
Re: GetMem verursacht Fehler
Zitat:
In dem Fall würde das Finden des Fehlers dann nicht so einfach, wenn auch keine Meldungen kommen, wenn man die entsprechenden Einstellungen aktiviert. |
Re: GetMem verursacht Fehler
Hab den Wavecode auskommentiert. Das einzige was da sowieso in Frage käme als Fehlerverursacher war "Move" (wenn es denn mein Fehler ist).
Scheint einwandfrei zu funktionieren. Alte Zeile
Delphi-Quellcode:
So scheints zu gehen.
if RPos+16<= waveDataSize then ReadLength:=16;
if RPos+16> waveDataSize then ReadLength:= (Rpos+16)-waveDataSize; DateiStream.Read(DataBlock16[0],readlength*2); // Fülle das DatenBlock Array Move(DataBlock16[0], waveData16[RPos], length(DataBlock16)*2); // Verschiebe den DatenBlock ins WaveData Array
Delphi-Quellcode:
Gut, in dem Fall von dem DatenBlock hast du Recht hoika, da reicht ein statisches Array völlig aus. Habs auch umgestellt.
if RPos+16<= waveDataSize then ReadLength:=16;
if RPos+16> waveDataSize then ReadLength:= (Rpos+16)-waveDataSize; DateiStream.Read(DataBlock16[0],readlength*2); // Fülle das DatenBlock Array Move(DataBlock16[0], waveData16[RPos], ReadLength*2); // Verschiebe den DatenBlock ins WaveData Array Ich versteh nicht ganz wieso der Fehler auftritt. Length(DataBlock16) gibt doch die Anzahl der Elemente im Array zurück. Also 16 in meinem Fall. Am Ende der Datei, beim allerletzen Block, wenn weniger als 16 SmallInts auszulesen sind ists einerseits klar beim alten Code, dass das DataBlock Array nicht ganz gefüllt ist. Logisch. Nehmen wir an es gäbe noch 7 Einträge zu lesen, dann wäre ja nur 0-7 gefüllt, 8-15 hätte dann noch den Wert vom vorherigen Datenblock, richtig? Das klingt als Audiostream warscheinlich scheisse (-> knacksen), sollte aber doch keine Zugriffsverletzung verursachen? Ich lasse mir auch die PCM-Rohdaten anzeigen als Welle, und das funktioniert von Anfang bis Ende einwandfrei. Kein Fehler... Normalerweise bin ich C# und VB.NET Benutzer, da ging sowas immer einwandfrei.. bin auf FPC weil ich Platformunabhängigkeit will und Delphi eben noch aus dem Informatikunterricht kenn (da haben wir aber nicht mehr als Ampelprogramme gemacht :-D ) Kann mir jemand von euch erklären wieso gerade das dann bei getmem einen Fehler auslöst? Gruß, Jan |
Re: GetMem verursacht Fehler
Hallo,
per FillChar(DataBlock, #0) kann ein array komplett auf 0 gesetzt werden. Bei dem Code fällt mir auf. 1. kein Assert DataBlock16 ist ja wohl ein maximal 16 SmallInt grosser Block ein Assert(readlength<=16, 'readlength>16') vor der Benutzung würde das sicherstellen 2. mal prüfen if RPos+16<= waveDataSize then ReadLength:=16; ReadLength = 16, OK DateiStream.Read(DataBlock16[0],readlength*2); jetzt werden 32 SmallInt in den 16er Block gelesen ? 3. Rechtschreibung :) mal heisst es readlength, dann wieder ReadLength ich setze immer ein Typ-Kürzel davor, bei Integer also iReadLength Heiko |
Re: GetMem verursacht Fehler
Ich denke es geht um Lazarus und FreePascalCompiler... und vorrausgesetzt der Fehler tritt getestet beim GetMem auf:
Evtl. kommt FPC mit 555 Byte für einen Byte-Pointer nicht klar und reserviert entgegen der Anforderung nur 1 Byte. Evtl Testweise mal einen untypisierten Pointer verwenden? Zumindest im Startpost wird geschrieben, dass der dort gepostet Code einen Fehler auslöst. |
Re: GetMem verursacht Fehler
dann könnte man es auch direkt so testen
Delphi-Quellcode:
getmem(Pointer(c), 555);
|
Re: GetMem verursacht Fehler
Nicht ganz. Die 16 steht für die BitRate des WaveStreams.
Bedeutet also das ein Wert der Welle in den Rohdaten als SmallInt dagestellt wird. DataBlock16 ist ein SmallInt Array mit 16 Einträgen. Um das zu füllen muss ich ja dann logischerweise 32byte auslesen. Bei der Rechtschreibung hast du natürlich Recht, ich mach die anständigen Formatierungen normalerweise erst wenn ein Codeblock so funktioniert wie ich das will, auch wenns stilistisch vielleicht nicht das Beste sein mag :mrgreen: @Satty67: Der untypisierte Pointer hat auch nicht funktioniert, das hatte ich auch probiert. Ist aber bei jedem Wert oberhalb der Grenze passiert. Die Grenze hab ich nicht genau getestet, sie lag aber irgenwo zwischen 500-550. Alles darunter ging, alles darüber nicht. Wie gesagt, das mit der unteren Zeile funktioniert jetzt ja alles. Gibt keinen Fehler mehr aus. Aber ich versteh einfach nicht wieso das so ist. Was den Speicher da kaputtmachen sollte. Gruß, Jan |
Re: GetMem verursacht Fehler
500-550 ... könnt man jetzt glatt auf di Idee kommen, daß es 512 Byte sind :stupid:
Ich kenn den Speichermanager von FPC nicht, aber entweder hat der selber schon ein Problem, oder du hast irgendwo einen Bufferoverrun oder Ähnliches und zerstörst da die Verwaltungsdaten des MM. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:54 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz