Speicher freigeben, Threads, ProgressDialog...

Alles rund um die Programmierung mit Qt
solarix
Beiträge: 1133
Registriert: 7. Juni 2007 19:25

Beitrag von solarix »

pfid hat geschrieben:Finger weg ist in meinen Augen etwas übertrieben. Was wenn der Thread aus irgendwelchen Gründen hängt, und sich nicht beenden lässt?
Da gibt es drei Varianten:
1) falls du den kompletten Code selbst in der Hand hast: ein Thread hat sich gefaelligst nicht aufzuhaengen!
2) falls externe Klassen/Methoden verwendet werden:
2a) egal... dann haengt halt die komplette app.. dann muss der User entscheiden.
2b) dann wird der Thread halt gekillt... mit allen Konsequenzen.....!
pfid hat geschrieben: ...Alles was der User allokiert hat, muss logischerweise der User wegräumen, was allerdings von der Nebenläufigkeit unabhängig ist.
Sprich: das Objekt kann der User auch nach QThread::terminate löschen, wenn dort immer noch der Speicher wächst, fehlt vielleicht irgendwo ein delete?
Genau da liegt der Hund begraben... der Thread kann irgendwo gekillt werden. Wenn du z.B. aus dem Thread eine (externe) Funktion aufrufst welche kurzzeitig dynamisch Speicher benoetigt und mittendrinn gekillt wird, wie willst du dann diesen Speicher wieder freigeben? Oder wenn eine Instanz einer (externen) Klasse dynamischen Speicher verwaltet und diese Instanz auf dem Stack angelegt wird:

Code: Alles auswählen

 ... run() {
  if (...) { 
    QString s("dingsda");
    ...
    ... // hier wird der Thread gekillt -> MLK
  } // DTor von "s" 
}
Daher bin ich ausnahmsweise gleicher Meinung wie MS: Haende weg :wink:
pfid
Beiträge: 535
Registriert: 22. Februar 2008 16:59

Beitrag von pfid »

solarix hat geschrieben:
pfid hat geschrieben:Finger weg ist in meinen Augen etwas übertrieben. Was wenn der Thread aus irgendwelchen Gründen hängt, und sich nicht beenden lässt?
Da gibt es drei Varianten:
1) falls du den kompletten Code selbst in der Hand hast: ein Thread hat sich gefaelligst nicht aufzuhaengen!
2) falls externe Klassen/Methoden verwendet werden:
2a) egal... dann haengt halt die komplette app.. dann muss der User entscheiden.
2b) dann wird der Thread halt gekillt... mit allen Konsequenzen.....!

Daher bin ich ausnahmsweise gleicher Meinung wie MS: Haende weg :wink:
Nun, mir fallen da schon einige Möglichkeiten ein. Selbst wenn ich meinen Code selbst in der Hand habe, die Vorstellung, der Thread hat sich gefälligst nicht aufzuhängen ist zwar sehr löblich, aber eben so utopisch. Was ist, wenn er in einem Systemcall stecken bleibt, worauf du keinen Einfluß hast? Netzwek, IPC, Filesystem, sonst wo?
Hier auf Arbeit habe ich beispielsweise das konkrete Problem, dass Threads des öfteren stehenbleiben, weil Signale des Betriebssystems verloren gehen (wie genau das technisch passiert, und was dagegen zu tun ist, sei hier mal dahingestellt).

Nach meiner Erfahrung und mit dem eben Geschildertem sieht es für mich daher so aus:
- einen Thread, der niemals hängen bleibt, ist je nach Anforderung unmöglich
- für solche Fälle kann/darf/soll ein solcher Thread jederzeit gecancelt werden, ohne dass es zu Problemen kommt

Was den Speicher angeht, stellt sich mir das auch eher einfach dar:
- wird Speicher in einer externen Lib allokiert, sollte dies unabhängig von meinem Code und meinen Threads funktionieren, und auch wieder freigegeben werden können, egal ob ich in meinem Code Threads cancel oder nicht
- wird Speicher in meinem Code allokiert, sollte es noch viel einfacher sein, durch eintsprechendene Destruktoren das ganze wieder freizugeben

Um Mißverständnissen vorzubeugen:
Natürlich sollte der Weg immer sein, einen Thread "sauber" zu beenden. Und bei den Anforderungen des TEs sollte das vermutlich auch Problemlos sichergestellt werden können, so dass sich diese Fragen hier gar nicht erst stellen.

[edit] mE muss der Stack beim Löschen des Objekts ganz normal aufgeräumt werden, und hat prinzipiell erstmal nichts mit Threads zu tun.
solarix
Beiträge: 1133
Registriert: 7. Juni 2007 19:25

Beitrag von solarix »

pfid hat geschrieben: [...] Was ist, wenn er in einem Systemcall stecken bleibt, worauf du keinen Einfluß hast? Netzwek, IPC, Filesystem, sonst wo?

Genau das meinte ich mit "extern"... also Punkt 2 :wink:
pfid hat geschrieben: einen Thread, der niemals hängen bleibt, ist je nach Anforderung unmöglich

Das stimmt... aber in einem solchen (seltenen) Fall würde ich trotzdem terminate() soweit wie möglich vermeiden. Filesysteme und Netzwerk haben meist irgendwann ein Timeout.. dann hängt Thread halt.. so what? Hauptsache die GUI handelt das sauber und zeigt dem Anwender, dass das Programm nicht tot ist. Oder man sendet dem Thread eine saubere Shutdown-Anweisung und vergisst ihn (sollte er sich nochmals erholen, kann er sich dann sauber beenden). Könntest du in deinem Fall nicht auch ein Timeout einbauen und entsprechend reagieren (falls keine Reaktion halt das "verlorene" Signal wiederholen..)
pfid hat geschrieben: für solche Fälle kann/darf/soll ein solcher Thread jederzeit gecancelt werden, ohne dass es zu Problemen kommt

Soll kann man so stehen lassen. Ada95, Java und .Net verhalten sich da auch etwas anderst... aber du verwendest C++...
pfid hat geschrieben: Was den Speicher angeht, stellt sich mir das auch eher einfach dar:
- wird Speicher in einer externen Lib allokiert, sollte dies unabhängig von meinem Code und meinen Threads funktionieren, und auch wieder freigegeben werden können, egal ob ich in meinem Code Threads cancel oder nicht
- wird Speicher in meinem Code allokiert, sollte es noch viel einfacher sein, durch entsprechende Destruktoren das ganze wieder freizugeben

Leider nicht möglich.. Es wird kein Code mehr im Userspace aufgerufen..

pfid hat geschrieben: Um Mißverständnissen vorzubeugen:
Natürlich sollte der Weg immer sein, einen Thread "sauber" zu beenden. Und bei den Anforderungen des TEs sollte das vermutlich auch Problemlos sichergestellt werden können, so dass sich diese Fragen hier gar nicht erst stellen.
Ack

:wink:
pfid
Beiträge: 535
Registriert: 22. Februar 2008 16:59

Beitrag von pfid »

solarix hat geschrieben: Leider nicht möglich.. Es wird kein Code mehr im Userspace aufgerufen..
Ja gut, wenn du das Programm beendest, isses auch wurscht was mit den Ressourcen ist ;)

[edit] Zum Thema Timeout einbauen:
Das Signal IST das Timeout, um msgrcv zu unterbrechen. Fehlt das Signal, steht man für immer in msgrcv (oder bis eine Nachricht eintrifft).

Die Frage ist halt, willst du in deinem Programm potentiell "festgefahrene" Threads anhäufen, nur weil du sie nicht canceln willst? ("Hauptsache die GUI handelt das sauber" ...)
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag von RHBaum »

fuer mich ist das Terminate Thread was, was der kaptain macht, kurz bevor das schiff vor dem Entern steht und es nicht in Feindeshand geraet :-)

TerminateThread ruf ich auf, wenn das programm sich soweiso beendet, und unter windows beendet sich das prog ned, solange ein thread laeuft ... im taskmanager muss man den dann gewaltsam beenden, und dann kommt die beruehmte "programm reagiert nicht" meldung ... etc.

Um das zu vermeinden, klar, iss nen terminate thread sinnvoll, aber im Normalbetrieb, und wenn das prog noch ne weile laufen sollt, iss terminatethread keine option.
Was ist, wenn er in einem Systemcall stecken bleibt, worauf du keinen Einfluß hast? Netzwek, IPC, Filesystem, sonst wo?
unter linux kenn ich mich ned soo aus, aber unter windows ... wo hat man systemcalls die im nirvana enden ?
die meisten was netzwerk betrifft, gibts immer ne version mit timout zeit, die sollt man auch nutzen ...
Viele ressourcenzugriffe liefern automatisch nen timeout (fehlercode beim zugriff) .....

Problematischer sind mehr die dlls von 3herstellern, die bleiben wirklich ab und an mal haengen. Aber da terminate und runterfahren .... alles andere iss eh gefaehrlich.

Ciao ...
pfid
Beiträge: 535
Registriert: 22. Februar 2008 16:59

Beitrag von pfid »

RHBaum hat geschrieben: Problematischer sind mehr die dlls von 3herstellern, die bleiben wirklich ab und an mal haengen. Aber da terminate und runterfahren .... alles andere iss eh gefaehrlich.
Kommt auf deine Anforderung an. Generell zu sagen "schalt dein Programm aus, wenn dein Thread irgendwo steht" ist etwas krass. Ich kann dir nur sagen, dass bei meinem Programm die Anforderung ist, dass es weiterläuft. Es sitzt auch kein Benutzer dahinter der Buttons klickt, da es eine Konsolenanwendung ist die im Hintergrund läuft ;)

Ausserdem ging es hier doch nur um die Frage, ob das Canceln eines Threads zum Memoryleak führt ;)

[edit] Und wie schon erwähnt, bei msgrcv gibts kein Timeout.
solarix
Beiträge: 1133
Registriert: 7. Juni 2007 19:25

Beitrag von solarix »

pfid hat geschrieben: Ausserdem ging es hier doch nur um die Frage, ob das Canceln eines Threads zum Memoryleak führt ;)
Nicht "ob" sondern eher "warum"... :wink:
pfid hat geschrieben: Und wie schon erwähnt, bei msgrcv gibts kein Timeout.
Wenn ihr Probleme mit den Signals habt, dann sendet dem Thread mit msgsnd() eine Meldung, dass er sich zu beenden hat :wink: [EDIT] oder ruft msgrcv nur auf, wenn auch wirklich eine Meldung pending ist (msgctl)

Aber mit "msgrcv" sind wir nun endgueltig OT...
pfid
Beiträge: 535
Registriert: 22. Februar 2008 16:59

Beitrag von pfid »

solarix hat geschrieben:
pfid hat geschrieben: Ausserdem ging es hier doch nur um die Frage, ob das Canceln eines Threads zum Memoryleak führt ;)
Nicht "ob" sondern eher "warum"... :wink:
Und eine Antwort auf die Frage haben wir immer noch nicht :) Obwohl ich ja immer noch von einem ob ausgehe :P
solarix hat geschrieben: Aber mit "msgrcv" sind wir nun endgueltig OT...
Da stimme ich zu ;)
acdc
Beiträge: 82
Registriert: 23. Oktober 2007 18:56

noch eine Frage

Beitrag von acdc »

Ich habe übergebe mittels Konstrukter meinem Thread ein QFile. Nun starte ich zwei Threads, in denen ich in ein und die Selbe Datei schreibe. Leider etsteht dabei nicht das richtige Ergebnis.
Was muss ich machen, dass die Datei von beiden Threads verwendet werden kann und es keinen Datensalat gibt?

mfg
acdc
Antworten