Programm bleibt bei WaitForSingleObject hängen...
-
hustbaer schrieb:
CodeFinder schrieb:
hustbaer schrieb:
[...] Die ganze "volatile Geschichte" in dem Code vom CodeFinder ist IMHO ganz böse rumgepfuscht. [...]
*Shot down in flames*
... Wieso ?Einfach so

Ok, ernst. Weil volatile in C++ schonmal sowieso nicht gescheit definiert ist (z.B. ist es nun ne memory-barrier oder nicht?). Weil du bloss beim Schreiben auf volatile castest und beim Lesen nicht. Weil das alles einfach fürchterlich ist.
Deine Erklärung find ich n bissl lari fari^^ ...Hm...na volatile unterdrückt Compileroptimierungen (siehe: http://www.cppreference.com/keywords/all.html)
volatile
The volatile keyword is an implementation-dependent modifier, used when declaring variables, which prevents the compiler from optimizing those variables. Volatile should be used with variables whose value can change in unexpected ways (i.e. through an interrupt), which could conflict with optimizations that the compiler might perform.hustbaer schrieb:
Aber das ist ja nicht das einzige grauenhafte an dem Code...
Die "static" Daten sind sehr sehr schauderhaft, und nen Thread in C++ mit _endthreadex() abzubrechen ist auch schauderhaft. "return 0" aus der thread function wäre dir wohl zu trivial gewesen oder wie?
Wieso sind static-Daten schauderhaft ? Wie würdest Du denn die Daten definieren ? Global ? Oha...
Das mit dem _endthreadex() ist gewollt...man _sollte_ Threads mit _endthreadex() beenden, das return (0) danach ist also nur obligatorisch
.
Siehe:Terminating a thread with a call to endthread or _endthreadex helps ensure proper recovery of resources allocated for the thread.
Quelle: http://msdn2.microsoft.com/en-us/library/hw264s73(VS.80).aspx
-
man _sollte_ Threads mit _endthreadex() beenden
NIE!!!
-
b schrieb:
man _sollte_ Threads mit _endthreadex() beenden
NIE!!!
Also manchmal gehen mir diese 'Non-Sinns-Aussagen' von ungereggten Trolls ja doch extrem auf n S***
.Kannst Du das auch schlüssig begründen/belegen ?
-
_endthreadex is called automatically
-
_endthreadex helps ensure proper
Was meinst Du warum schreiben die das ?
-
Um dich zu verwirren.
-
Naja ich bleib bei meiner Meinung.
Das war auch mein letzter Post diesbezüglich.
-
@CodeFinder:
Blödsinn ^3.
Sorry, aber ich weiss wovon ich rede.#1:
MSDN schrieb:
You can call _endthread or _endthreadex explicitly to terminate a thread; however, _endthread or _endthreadex is called automatically when the thread returns from the routine passed as a parameter to _beginthread or _beginthreadex.
Und nu denk mal drüber nach was in C++ anders ist als in C:
#2:unsigned __stdcall ThreadFn(void*) { std::string foo = "012345678901234567890123456789"; _endthreadex(0); return 0; // braucht ein "guter" compiler hier garnicht }Und jetzt beobachte dein Memory-Leak. Holladeroh. Glaubst du der C++ Compiler kann zaubern und ruft alle Destruktoren von auto-Variablen auf wenn du das so machst? Nööööööhöhö.
_endthreadex ist unnötig und böse.Und volatile ist murks, es sei denn man weiss genau was man tut.
-
Hm Du meinst, das durch den Aufruf von _endthreadex() der Aufruf des Destuktor's (Klasse ist ja rille) verhindert wird
?
-
Hab diese Sachen mit volatile (und auch endthread) außem Petzold. Dachte das wär noch gültig
.
-
CodeFinder schrieb:
Hab diese Sachen mit volatile (und auch endthread) außem Petzold. Dachte das wär noch gültig
.Nur um Dich zu erinnern: Petzold ist C und nicht C++! Von Destruktoren war da nie die Rede. Sofern hat er einfach entsprechend vor dem Aufruf aufräumen müssen. Ein C++ Programmierer wird aber oft genug nicht weit genug denken was für Konsequenzen eine Funktion wie _endthreadex hat!
_endthreadex ist wirklich zu vermeiden!
Die beste Methode ist immer noch einfach aus der Thread Funktion zu returnieren und die CRT oder das OS den Rest machen zu lassen!Ich kannmich das hustbaer nur anschliessen!
-
Jops ok, man lernt nie aus
. Schankedön
.
-
CodeFinder schrieb:
Hm Du meinst, das durch den Aufruf von _endthreadex() der Aufruf des Destuktor's (Klasse ist ja rille) verhindert wird
?Ich meine es, und ich hab es sogar ausprobiert bevor ich hier gepostet habe

Kannst ja einfach mal ne Klasse zum probieren machen:class foo { public: foo() { std::cout << "foo ctor called." << std::endl; } ~foo() { std::cout << "foo dtor called." << std::endl; } };Wenn du dann in der ThreadFn eine lokale Variable vom Typ foo anlegst siehst du dass bei Verwendeung von _endthreadex() der ctor aufgerufen wird, der dtor allerdings nicht. Wenn du mittels return rausgehst werden beide aufgerufen.
Ausserdem machst du mit dem Aufruf von _endthreadex() die Funktion von _beginthreadex abhängig, d.h. die funktioniert dann in keinem Framework mehr welches vielleicht selbst noch cleanup Code ausführen will, oder auch nicht in Programmen die CreateThread oder _beginthread (ohne ex) verwenden.
In C++ sollte man einen Thread oder auch das Programm immer nur dadurch verlassen/beenden dass man aus der Thread Function bzw. main mittels return zurückkehrt. "exit(0)" ist in C++ auch "böse".
-
Jo danke auch nochmal @hustbaer!
Allerdings nutze ich CreateThread (bzw. _beginthread) sowieso nicht, wegen der CRT-Leaks. Aber hast natürlich Recht mit Deinem Einwand
.PS: Hatte ich in einem früheren Post gefragt, _wo_ Du Deine 'thread-bezogenen' (id est: Infos für den Thread selbst, Kontrollvariablen und Sync-Objekte, welches ja idr. alles in einem struct zusammengefasst wird) Daten definierst, da Du -so kam das rüber- etwas gegen statische Variablen hast^^.
PPS: Muss man den Zugriff auf die 'Thread-Datenstruktur' auch syncronisieren ? Ist das nicht eigentlich überflüssig ?
-
Äh.
Ich verwende niemals static Daten wenn es sich vermeiden lässt.
Ich programmiere schliesslich auch meistens "objektorientiert" (ein Unwort, weil es viel zu viele Meinungen darüber gibt wie OOP nun auszusehen hat, aber egal).Wenn ich ein Objekt habe welches einen eigenen Thread rausstartet, dann stehen die gemeinsam genutzten Daten natürlich als non-static Member in diesem Objekt. Der Thread bekommt einen Zeiger auf das Objekt mit, fertig.
Daten die bloss der Thread alleine braucht lege ich entweder im Thread mit new an (wenns gross ist), oder sie wandern einfach auf dessen Stack, wofür hat man den schliesslich.Wenn ein Thread detached läuft dann bekommt er meistens einen Zeiger auf die Daten die er braucht mit, wobei ich dann die Ownership an den Thread übergebe, d.h. der muss sich darum kümmern das "Datenobjekt" mittels delete wieder wegzumachen.
Und was das Zugriffe Synchronisieren angeht: du musst Zugriffe auf sämtliche Daten synchronisieren die von mehreren Threads verwendet werden. Einzige Ausnahme: wenn *ALLE* Threads nur lesend darauf zugreifen. Also z.B. Lookup-Tabellen die du einmal mit Werten befüllst (bevor du andere Threads rausstartest), und danach NURMEHR liest. Sobald aber irgendwer schreibt musst du synchronisieren.
Daten die ausschliesslich ein Thread verwendet sind natürlich nicht betroffen, wobei natürlich auch egal ist wenn das nicht der "Hauptthread" ist.