AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

GetMem verursacht Fehler

Ein Thema von JanW · begonnen am 24. Jun 2009 · letzter Beitrag vom 27. Jun 2009
Antwort Antwort
Seite 1 von 2  1 2      
JanW

Registriert seit: 5. Jun 2009
8 Beiträge
 
Lazarus
 
#1

GetMem verursacht Fehler

  Alt 24. Jun 2009, 07:37
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:
procedure TForm1.Button6Click(Sender: TObject);
var
 c: ^byte;
begin
  getmem(c, 555); //<- Da tritt der Fehler auf
  freemem(c);
end;
SIGSEGV. Egal was.
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...

Gruß,
Jan
Jan
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.582 Beiträge
 
Delphi 11 Alexandria
 
#2

Re: GetMem verursacht Fehler

  Alt 24. Jun 2009, 07:53
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 hier erklärt.

Schreib am besten in deinen Projektquelltext (Projekt --> Quelltext anzeigen) nach dem begin:ReportMemoryLeaksOnShutdown := True; (geht erst am Delphi 2006)
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.
Sebastian Jänicke
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!
  Mit Zitat antworten Zitat
hoika

Registriert seit: 5. Jul 2006
Ort: Magdeburg
8.275 Beiträge
 
Delphi 10.4 Sydney
 
#3

Re: GetMem verursacht Fehler

  Alt 24. Jun 2009, 07:55
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
Heiko
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.582 Beiträge
 
Delphi 11 Alexandria
 
#4

Re: GetMem verursacht Fehler

  Alt 24. Jun 2009, 07:59
Zitat von hoika:
2. Kommentier den Wave-Code komplett aus und dann stückweise wieder "rein"
Wobei das bei einem solchen Speicherfehler nicht unbedingt den Fehler aufdeckt. Denn der kann ganz woanders auftreten und bei Änderungen zufällig auftreten oder nicht. Leider.

In dem Fall würde das Finden des Fehlers dann nicht so einfach, wenn auch keine Meldungen kommen, wenn man die entsprechenden Einstellungen aktiviert.
Sebastian Jänicke
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!
  Mit Zitat antworten Zitat
JanW

Registriert seit: 5. Jun 2009
8 Beiträge
 
Lazarus
 
#5

Re: GetMem verursacht Fehler

  Alt 24. Jun 2009, 08:32
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:
      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
So scheints zu gehen.
Delphi-Quellcode:
      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
Gut, in dem Fall von dem DatenBlock hast du Recht hoika, da reicht ein statisches Array völlig aus. Habs auch umgestellt.
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 )

Kann mir jemand von euch erklären wieso gerade das dann bei getmem einen Fehler auslöst?

Gruß,
Jan
Jan
  Mit Zitat antworten Zitat
hoika

Registriert seit: 5. Jul 2006
Ort: Magdeburg
8.275 Beiträge
 
Delphi 10.4 Sydney
 
#6

Re: GetMem verursacht Fehler

  Alt 24. Jun 2009, 08:39
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
Heiko
  Mit Zitat antworten Zitat
Satty67

Registriert seit: 24. Feb 2007
Ort: Baden
1.566 Beiträge
 
Delphi 2007 Professional
 
#7

Re: GetMem verursacht Fehler

  Alt 24. Jun 2009, 08:43
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.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.063 Beiträge
 
Delphi 12 Athens
 
#8

Re: GetMem verursacht Fehler

  Alt 24. Jun 2009, 08:49
dann könnte man es auch direkt so testen
getmem(Pointer(c), 555);
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat
JanW

Registriert seit: 5. Jun 2009
8 Beiträge
 
Lazarus
 
#9

Re: GetMem verursacht Fehler

  Alt 24. Jun 2009, 08:50
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

@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
Jan
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.063 Beiträge
 
Delphi 12 Athens
 
#10

Re: GetMem verursacht Fehler

  Alt 24. Jun 2009, 08:59
500-550 ... könnt man jetzt glatt auf di Idee kommen, daß es 512 Byte sind

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.
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:09 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz