![]() |
Thread-Parameter auf dem Stack übergeben
Ich kann einem Thread Parameter entweder über den Heap oder über den Stack mitgeben. Übergebe ich sie über den Heap, muss ich Speicher reservieren und im Thread natürlich wieder freigeben.
Aber wie funktioniert das, wenn ich die Parameter über den Stack übergebe? Siehe dazu das Beispiel. Wer gibt da wann und wie den Speicher wieder frei?
Delphi-Quellcode:
type
TThreadParams = packed record Number: Integer; Text: String; end; PThreadParams = ^TThreadParams; function IntToStr(Int: integer): string; begin Str(Int, result); end; function ThreadFunc(tp: PThreadParams): Integer; var Number: Integer; Text: String; s: String; begin Number := PThreadParams(tp)^.Number; Text := PThreadParams(tp)^.Text; s := 'Zahl: ' + IntToStr(Number) + #13#10 + 'Text: ' + Text; Result := MessageBox(0, PChar(s), 'Thread', MB_YESNO or MB_ICONINFORMATION); end; var tp: TThreadParams; Thread: THandle; ThreadID: Cardinal; ExitCode: Cardinal; begin tp.Number := 42; tp.Text := 'Die Antwort.'; Thread := BeginThread(nil, 0, @ThreadFunc, @tp, 0, ThreadID); WaitForSingleObject(Thread, INFINITE); GetExitCodeThread(Thread, ExitCode); case ExitCode of IDYES: Writeln('Benutrzer hat "Ja" angeklickt.'); IDNO: Writeln('Benutzer hat "Nein" angeklickt.'); end; CloseHandle(Thread); Readln; end. |
Re: TRhread-Parameter auf dem Stack übergeben
Das wird so nicht gehen. Du musst dafür sorgen, dass die Parameter auf dem Stack nicht überschrieben werden, während der Thread darauf zugreift - was im schlimmsten Fall über die gesamte Threadlaufzeit geschieht. Für diese Zeit musst du auf den Thread warten, da ein Return aus der aktuellen Methode dafür Sorgen würde, dass dein Parameter Freiwild wird und vom nächsten Aufruf im erzeugenden Thread höchstwahrscheinlich gründlich zerlegt wird. Was natürlich bedeuten würde, dass Threads in dem Fall eher.. naja, sinnlos sind.
Aber zum eigentlich Thema: den Speicher freigeben muss der Aufrufer, wenn es der Thread nicht tut. Da du den Speicher über den Stack holst, musst du ihn *garnicht* freigeben, du darfst es sogar nicht mal, nicht im Thread und nirgendwo sonst, das macht nämlich deine Methode automatisch beim Return. |
Re: Thread-Parameter auf dem Stack übergeben
Derzeit übergibst du eine globale Variable.
Solange du im Mainthread die golabel Variable nicht änderst (was du ja auf Grund von WaitForsingleObject ja erriechst) kein Problem. Wenn du den Parameter wirklich auf dem Stack hast (loakle Variable) wird diese spätestens nach Abschluss der Prozedur ungültig. Also nur Heap benutzen! |
Re: Thread-Parameter auf dem Stack übergeben
Dass es ohne warten nicht funktionieren würde ist klar, aber das tue ich ja in meinem Fall. Und was das Freigeben angeht, der Speicher auf dem Stack wird beim Verlassen der Funktion automatisch vom Betriebssystem aufgeräumt. Habe ich das so richtig verstanden?
@sirius: Stimmt, hier ist sie ja global, also auf dem Heap. Dann muss ich das noch mal umbauen. So sollte es eigentlich sein:
Delphi-Quellcode:
function ThreadFunc(tp: PThreadParams): Integer;
var Number: Integer; Text: String; s: String; begin Number := PThreadParams(tp)^.Number; Text := PThreadParams(tp)^.Text; s := 'Zahl: ' + IntToStr(Number) + #13#10 + 'Text: ' + Text; Result := MessageBox(0, PChar(s), 'Thread', MB_YESNO or MB_ICONINFORMATION); end; procedure RunThread; var tp: TThreadParams; Thread: THandle; ThreadID: Cardinal; ExitCode: Cardinal; begin tp.Number := 42; tp.Text := 'Die Antwort.'; Thread := BeginThread(nil, 0, @ThreadFunc, @tp, 0, ThreadID); WaitForSingleObject(Thread, INFINITE); GetExitCodeThread(Thread, ExitCode); case ExitCode of IDYES: Writeln('Benutrzer hat "Ja" angeklickt.'); IDNO: Writeln('Benutzer hat "Nein" angeklickt.'); end; CloseHandle(Thread); end; |
Re: Thread-Parameter auf dem Stack übergeben
du übergibst den Parameter ja gar nicht über den Stack. Da es eine globale Variable ist liegt diese nicht auf dem Stack. Aber selbst wenn sie auf dem Stack liegen würde übergibst du sie nicht über den Stack sondern du übergibst ja dem Thread generell nur einen Pointer auf Daten die irgendwo liegen. Und du musst nur dafür sorgen das die Daten worauf der Pointer zeigt auch noch da sind wenn über den Pointer darauf zugegriffen wird.
Dadurch das du auf den thread wartest bis er beendet ist würde der Inhalt auf dem Stack auch unverändert bleiben. Der Stack wird übrigens nicht vom Betriebssystem aufgeräumt. Je nach Calling Convention wird der Stack dort aufgeräumt wo die Funktion aufgerufen wurde oder eben in der Funktion. Wenn du dir den asm-code ansiehst wirst du sehen das explizit funktionen aufgerufen werden die den Stack auf- und abbauen. |
Re: Thread-Parameter auf dem Stack übergeben
Zitat:
Ein kleines Beispiel dazu: -Eintritt in die Methode: SP steht auf 1000 -Methode schnapp sich 100 Byte Stackspeicher: SP auf 1100 -Method gedönst rum... -Method gibt Stackspeicher frei: SP wieder auf 1000 -ret: SP auf 996 (für 32er-Systeme) |
Re: Thread-Parameter auf dem Stack übergeben
Ich habe das Beispiel geändert. Jetzt liegt der Thread-Parameter auf dem Stack. Damit dass das Betriebssystem den Stack aufräumt, hab eich mich wohl etwas ungenau ausgedrückt. Ich wollte damit ausdrücken, dass dies automatisch geschieht ohne dass man als zusätzlichen, eigenen Code dafür schreiben müsste, wie man es muss, wenn man den Parameter über den Heap übergibt.
|
Re: Thread-Parameter auf dem Stack übergeben
bischen Krümelkacken: Der stackpointer läuft rückwärts, wird also von oben nach unten gefüllt. Pack man was auf den Stack drauf wird der Stackpointer decrementiert (zeigt also auf eine niederigere Adresse als vorher)
|
Re: Thread-Parameter auf dem Stack übergeben
Zitat:
Und als Ergänzung noch zu Dax: Auf Grund von Codeoptimierung kann es passieren, dass die Gültigkeit schon vor Ablauf der Funktion aufgehoben wird und der Stackplatz von einer anderen lokalen Variable belegt wird. |
Re: Thread-Parameter auf dem Stack übergeben
@sirius: Die Codeoptimierung sollte aber auch berücksichtigen das ein Pointer auf die lokale Variable verwendet wurde und somit die Gültigkeit länger anhält. In Sprachen wie C gibt es dafür volatile um das weg optimieren zu verhindern (zum Beispiel für so einen Fall wenn ein anderer Thread noch darauf zugreifen könnte). In Delphi ist mir diesbezüglich nichts bekannt.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:10 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