Registriert: Di Nov 29, 2005 21:11 Beiträge: 88 Wohnort: Bonn
Moin!
Ich schreibe im Moment eine Konsolenanwendung mit SDL und OpenGL und wollte einen Timer zur Ausgabe der FPS einbauen.
Allerdings schmiert das gesamte Programm mit einer AccessViolation at 0x00000001 read 0x00000001 ab, wenn ich mehr als ein WriteLn in der TimerFunktion verwende.
So sieht sie aus
Code:
function TGame.FPSTimer(Interval: UInt32; param:Pointer):Integer;
var
event: PSDL_Event;
begin
WriteLn('FPSTimer');
event.type_:= SDL_USEREVENT;
event.user.code:=1;
event.user.data1:=nil;
event.user.data2:=nil;
if(SDL_PushEvent(event) <> 0)then
WriteLn('error pushing event');
Result :=1000;
end;
mit dem WriteLn alleine geht alles wunderbar.
Erst wollte ich direkt im Timer die Frames ausrechnen, anzeigen und die Variable zurücksetzen, aber im Wiki stand, dass das alles nicht threadsave ist und man events benutzen soll...
weiß jemand, warum er von dieser exotischen speicheradresse lesen will?
oder gibt es nen anderen weg, timer zu realisieren? ohne vcl und möglichst plattformunabhängig?
vielen dank für die Mühe!
edit:
der fehler tritt am ende der funktion auf, also gepusht wird...
ich teste noch weiter
editedit:
es öffnet sich außerdem dieses cpu-fenster, wenn der fehler kommt
wenn ich im einzelschritt durch den timer gehe und dann im cpu-fenster einmal f8 drücke und danach f9 läuft das programm weiter ohne die accesviolation, allerdings reagiert es nicht mehr wirklich auf seine umwelt...
edit3:
der fehler kommt auch, wenn ich das event nur definiere ohne es hinterher zu pushen
und er meint, event sei möglicherweise nicht initialisiert worden - kann man das bei records überhaupt??
event is ein pointer(zumindest sagt das sein Name) den du nicht initialisierst. Also darfst du ihn nicht dereferenzieren, was mit event.type_ automatisch geschieht (ist das selbe wie event^.type_)
Pointer sind eine der weniges stellen an der ich öfters die ungarische notation verwende. Würde die Variable auch PEvent nennen.
Registriert: Do Sep 02, 2004 19:42 Beiträge: 4158
Programmiersprache: FreePascal, C++
Was The-Winner dir damit sagen will: Reservier vorher den Speicher für deinen Pointer.
Code:
GetMem(event,SizeOf(SDL_Event));
Aber achtung: Schau am besten nochmal in der Libsdl nach, wie das ist mit dem Freigeben. Entweder SDL übernimmt das für dich oder du musst dich selber darum kümmern. Auch möglich ist, dass SDL den Inhalt des Records für sich noch einmal Kopiert. Dann müsstest du folgenden Code verwenden:
Code:
function TGame.FPSTimer(...):...;
var
event: SDL_Event;
begin
...deine Zuweisungen ...
if(SDL_PushEvent(@event) <> 0)then
WriteLn(...);
...
end;
Wenn du in den Dokumentationen dazu nichts findest, verwende mal due erste Methode, die ich beschrieben habe und schau mit so einer Speicherleckfinderunit nach, ob dabei ein Leck entsteht oder nicht. Wenn nein: Gut is, SDL gibt frei, wenn ja, benutze die zweite Methode, die ich beschrieben habe.
So eine Unit ist für FreePascal dabei mitgeliefert... Wie hieß die doch gleich... HeapTrc.
Gruß Lord Horazont
// edit Lossy: Pascaltags korrigiert
_________________ If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung. current projects: ManiacLab; aioxmpp zombofant network • my photostream „Writing code is like writing poetry“ - source unknown
„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb
Registriert: Do Dez 05, 2002 10:35 Beiträge: 4234 Wohnort: Dortmund
Also die erste Methode wird es wohl eher nicht sein, denn dann gehören die SDL Entwickler gesteinigt. Die Methode muss die übergebene Struktur kopieren etc. Alles andere würde dem Speichermanager von Delphi die Füße unter dem Boden wegziehen.
Denn die Speichermanager verwalten grundsätzlich alle immer selber eine Liste von reservierten Speicherbereichen. Und die sind Teil eine größeren Speicherblocks. Da darf niemand ohne die Erlaubniss den Speichermanagers etwas freigeben. Und dabei gibt es auch keine Ausnahme. Und solche SpeicherUnit wie FastMM stellen so etwas auch nur anhand diverser Listen fest, ob noch etwas übrig geblieben ist oder nicht.
PS: SDL_PushEvent Also der zweite Vorschlag von Lord Horazont ist der glückliche Gewinner.
Registriert: Do Sep 02, 2004 19:42 Beiträge: 4158
Programmiersprache: FreePascal, C++
Achja, was mich noch interessiert: Wie übergibst du deinen Timer an SDL? Eigentlich dürfte das Methoden doch garnicht annehmen. Oder hast du da noch eine "Vermittlerfunktion" zwischen?
Gruß Lord Horazont
P.S.: @Lossy: Sorry für die Tags.
_________________ If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung. current projects: ManiacLab; aioxmpp zombofant network • my photostream „Writing code is like writing poetry“ - source unknown
„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb
Registriert: Di Nov 29, 2005 21:11 Beiträge: 88 Wohnort: Bonn
Vielen Dank für den Tip mit dem Pointer!
Ich habe ein bisschen nachgedacht und bin auf folgende Lösung gekommen, wo ich mich auf den ersten Blick nicht um Speicherlecks kümmern muss:
Code:
function TGame.FPSTimer(Interval: UInt32; param:Pointer):Integer;
var
event: TSDL_UserEvent;
begin
WriteLn('FPSTimer');
event.type_:= SDL_USEREVENT;
event.code:=1;
event.data1:=nil;
event.data2:=nil;
SDL_PushEvent(@event)
Result :=1000;
end;
Also nicht Pointer zu nutzen, sondern direkt den Record.
Es scheint zu funktionieren, bis jetzt ist mir der Compiler noch nicht um die Ohren geflogen - ist es stilistisch auch akzeptabel?
Hui - jetzt muss ich erstmal die neuen Posts lesen =)
Registriert: Di Nov 29, 2005 21:11 Beiträge: 88 Wohnort: Bonn
oops, die lösung hatte der Lord ja schon gepostet - nächstes mal lese ich den code aufmerksamer durch ja, bei push_event wird die struktur kopiert, meine ich irgendwo gelesen zu haben
der timer ist ein SDL-Timer, den ich folgendermaßen erstelle:
SDL_AddTimer(1000, @TGame.FPSTimer, nil);
beantwortet das deine frage?
Mitglieder in diesem Forum: 0 Mitglieder und 8 Gäste
Du darfst keine neuen Themen in diesem Forum erstellen. Du darfst keine Antworten zu Themen in diesem Forum erstellen. Du darfst deine Beiträge in diesem Forum nicht ändern. Du darfst deine Beiträge in diesem Forum nicht löschen. Du darfst keine Dateianhänge in diesem Forum erstellen.