globale Funktion für alle threads



  • Ich versteh zwar nicht wieso eine Funktion global sein muss, damit mehrere Threads sie aufrufen können, aber die Antwort ob du etwas Synchronisieren musst liegt in der Antwort auf die Frage ob diese PostMessage Methode threadsafe ist. Wenn diese von mehreren Threads gleichzeitig ausgeführt werden kann, dann ist alles i.o.



  • pumuckl schrieb:

    Zum Einen hast du dir da ein nettes Speicherleck eingehandelt.

    Weißt du doch gar nicht. Vielleicht löscht PostMessage den string ja. Ein Leck gibts wenn LOGFILE_CLASS ein Makro ist dass irgendwas werfen kann oder PostMessage zu blöd zum Löschen ist. Vermutlich soll es aber tatsächlich so gemacht werden:

    void ErrorMsg(DWORD err, int type)
    {
       string err;
    
       //generiere exakte fehlermeldung mit err und type
       wnd->PostMessage(LOGFILE_CLASS, &err, 0)
    }
    


  • brotbernd schrieb:

    pumuckl schrieb:

    Zum Einen hast du dir da ein nettes Speicherleck eingehandelt.

    Weißt du doch gar nicht. Vielleicht löscht PostMessage den string ja. Ein Leck gibts wenn LOGFILE_CLASS ein Makro ist dass irgendwas werfen kann oder PostMessage zu blöd zum Löschen ist.

    Ich bin mal davon ausgegangen, dass PostMessage die übergebene Nachricht einfach nur darstellt und nicht gleich besitzergreifend ist und den String zerstört. Wäre zumindest höchst verwunderlich, konteruntuitiv und schlechtes Design, weil im Normalfall derjenige eine Ressource freigeben sollte, der sie auch erzeugt hat.



  • pumuckl schrieb:

    brotbernd schrieb:

    pumuckl schrieb:

    Zum Einen hast du dir da ein nettes Speicherleck eingehandelt.

    Weißt du doch gar nicht. Vielleicht löscht PostMessage den string ja. Ein Leck gibts wenn LOGFILE_CLASS ein Makro ist dass irgendwas werfen kann oder PostMessage zu blöd zum Löschen ist.

    Ich bin mal davon ausgegangen, dass PostMessage die übergebene Nachricht einfach nur darstellt und nicht gleich besitzergreifend ist und den String zerstört. Wäre zumindest höchst verwunderlich, konteruntuitiv und schlechtes Design, weil im Normalfall derjenige eine Ressource freigeben sollte, der sie auch erzeugt hat.

    Wow. das geht hier ja schnell mit Antworten; hätte ich nicht gedacht. 😋

    Der string selbst wird später wieder gelöscht, also stellt auf keinen Fall ein Speicherleck dar. PostMessage() sendet eine Message an den Mainthread vom jeweils aufgerufenen Thread, in dem ein Fehler statt gefunden hat.

    Ob PostMessage() threadsafe ist muss ich nochmal nachschalgen, aber danke für den Tipp.



  • Franz Will schrieb:

    void ErrorMsg(DWORD err, int type)
    {
       string *perr = new string(100); 
       wnd->PostMessage(LOGFILE_CLASS, perr, 0)
    }
    

    Es gibt doch nichts Schlimmeres als Code, der mit der MFC zu tun hat...



  • Wir bräuchten mal einen kurzen, knackigen Thread-Safety FAQ-Eintrag.



  • fdfdg schrieb:

    Wir bräuchten mal einen kurzen, knackigen Thread-Safety FAQ-Eintrag.

    Ein "kurzer, knackiger" FAQ-Eintrag zu einem sehr komplexen Thema ... wie soll das denn gehen?



  • brotbernd schrieb:

    Vermutlich soll es aber tatsächlich so gemacht werden:

    void ErrorMsg(DWORD err, int type)
    {
       string err;
    
       //generiere exakte fehlermeldung mit err und type
       wnd->PostMessage(LOGFILE_CLASS, &err, 0)
    }
    

    So sollte es ganz sicher nicht gemacht werden.
    PostMessage speichert ja nur den Zeiger in der Message-Queue, das Objekt auf das gezeigt wird wird dabei nicht geklont. -> Fehler, da das Objekt zu dem Zeitpunkt wo die Message bearbeitet wird schon lange nicht mehr existiert.



  • Das Problem ist, dass hier das C++ Forum ist und die meisten (zum Glück nicht alle) User hier wenig Ahnung von Programmierung mit WinAPI (und das ist letzendlich auch PostMessage(..)) haben.

    $imon



  • Ist mit string hier std::string gemeint? Wenn ja, welcher Konstruktor wird dann hier gerufen?

    string *perr = new string(100);
    

    Ich kenne keinen std::string Konstruktor der einen einzelnen int übernimmt.



  • hustbaer schrieb:

    Ein "kurzer, knackiger" FAQ-Eintrag zu einem sehr komplexen Thema ... wie soll das denn gehen?

    Indem man jede Menge auslässt und nur das für Anfänger notwendige abdeckt, natürlich. Z.B. muss wohl rein, dass
    - Zugriff auf gemeinsame Variablen problematisch ist (außer alle Beteiligten lesen nur)

    • static Variablen in Funktionen auch "gemeinsame" Variablen sind
      - man Zugriffe idR mit einem Mutex/Critical Section absichert
      - der shared state am besten möglichst klein gehalten wird
      - Threads durch Verlassen der Threadfunc beendet werden und wie man auf sie wartet

    Dazu noch Verweise auf boost::mutex und boost::mutex::scoped_lock , evtl auch die pthread_mutex_xx - und XxxCriticalSection -Funktionen. Schlussendlich natürlich boost::thread und zwei Wörter zum neuen Standard. Ein kleines Beispiel noch, das reicht dann auch.



  • theta schrieb:

    Das Problem ist, dass hier das C++ Forum ist und die meisten (zum Glück nicht alle) User hier wenig Ahnung von Programmierung mit WinAPI (und das ist letzendlich auch PostMessage(..)) haben.

    $imon

    Man muss von Windows bzw. der MFC nichtmal wissen dass es sie gibt, und sollte als halbwegs erfahrener C++ Programmierer doch ahnen können, dass sich hinter PostMessage etwas verbergen könnte, was eine Message postet. Behaupte ich mal.



  • fdfdg schrieb:

    ...

    - keine Exceptions aus 'ner Threadproc rausfliegen dürfen

    Fehlt sonst noch was essentielles?



  • @fdfdg:
    Es fehlt z.B. noch die Erklärung warum gewisse Dinge überhaupt nötig sind. Anfänger glauben sonst schnell dass sie das Thema verstanden haben, und fangen an falschen Code zu schreiben, weil sie meinen zu wissen dass in diesem oder jenem Spezialfall "eh nichts passieren kann".

    Und leider ist gerade das ein sehr schwieriges Thema.

    * CPU Reordering
    * Compiler Reordering
    * Cache-Coherency

    Als nächstes dann was eine Mutex überhaupt ist, und wie man sie richtig verwendet. Was Acquire- und Release-Semantik bedeutet, und inwiefern das mit Mutexen zu tun hat. Und natürlich was eine Condition-Variable ist + richtiger Verwendung.

    Was volatile in C++ macht und nicht macht, und warum es in den meisten Fällen weder nötig noch ausreichend ist.

    Dazu die von dir genannten Dinge.

    Dann hast du einen Artikel der weder kurz noch knackig ist, und den daher (fast) keiner mehr liest.

    Was ich meine ist: du kannst dir aussuchen ob du einen Artikel schreiben willst, der vermutlich mehr Schaden anrichtet als nützt, weil er ein falsches Gefühl der Sicherheit (im Sinn von "ich kenne mich aus") erzeugt. Dafür aber kurz genug ist dass ihn viele Leute lesen. Oder aber einen Artikel der wirklich das wichtigste erwähnt, dafür aber so lang ist, dass ihn kaum einer liest. Zumindest kaum einer derer die "nur schnell mal was wissen wollen".



  • Korrigiere mich bitte, falls ich falsch liege, aber: Deine genannten Punkte CPU Reordering, Compiler Reordering, Cache Coherency und volatile spielen doch gar keine Rolle wenn man alle gemeinsame-Daten-Zugriffe per Mutexe absichert, oder?

    Oder anders gefragt: Hat man nicht ein 100% sicheres Verhalten, wenn man alle solche "kritischen" Datenzugriffe durch Mutexe bzw Critical Sections absichert?



  • hustbaer schrieb:

    theta schrieb:

    Das Problem ist, dass hier das C++ Forum ist und die meisten (zum Glück nicht alle) User hier wenig Ahnung von Programmierung mit WinAPI (und das ist letzendlich auch PostMessage(..)) haben.

    $imon

    Man muss von Windows bzw. der MFC nichtmal wissen dass es sie gibt, und sollte als halbwegs erfahrener C++ Programmierer doch ahnen können, dass sich hinter PostMessage etwas verbergen könnte, was eine Message postet. Behaupte ich mal.

    Ehrlich gesagt hatte ich nicht damit gerechnet, dass es sich um eine MFC Methode handelt, da ich annahm dass es ein std::string sei und es mich gewundert hätte, dass die Methode einen Zeiger auf einen std::string nimmt. Am Konstruktor hätte ich aber sehen können, dass es irgendein anderer string ist.
    Was es für die Speicherverwaltung irgendwelcher strings bedeutet, wenn eine "Message gepostet" wird, weiß ich trotzdem nicht, bzw. ich wusste es nicht 😉



  • fdfdg schrieb:

    Oder anders gefragt: Hat man nicht ein 100% sicheres Verhalten, wenn man alle solche "kritischen" Datenzugriffe durch Mutexe bzw Critical Sections absichert?

    Klar. Wenn du alles korrekt synchronisierst, dann ist alles korrekt synchronisiert. Der Tricky Part ist nur alles korrekt zu synchronisieren.



  • Shade Of Mine schrieb:

    fdfdg schrieb:

    Oder anders gefragt: Hat man nicht ein 100% sicheres Verhalten, wenn man alle solche "kritischen" Datenzugriffe durch Mutexe bzw Critical Sections absichert?

    Klar. Wenn du alles korrekt synchronisierst, dann ist alles korrekt synchronisiert. Der Tricky Part ist nur alles korrekt zu synchronisieren.

    Jo, aber dann kann man damit den Multithreading-Neulingen doch eine einfache goldene Regel an die Hand geben. Dass das nicht immer einfach auszuführen ist, ist klar; immerhin aber verständlich und einfach zu merken 👍



  • fdfdg schrieb:

    Shade Of Mine schrieb:

    fdfdg schrieb:

    Oder anders gefragt: Hat man nicht ein 100% sicheres Verhalten, wenn man alle solche "kritischen" Datenzugriffe durch Mutexe bzw Critical Sections absichert?

    Klar. Wenn du alles korrekt synchronisierst, dann ist alles korrekt synchronisiert. Der Tricky Part ist nur alles korrekt zu synchronisieren.

    Jo, aber dann kann man damit den Multithreading-Neulingen doch eine einfache goldene Regel an die Hand geben. Dass das nicht immer einfach auszuführen ist, ist klar; immerhin aber verständlich und einfach zu merken 👍

    Nein. Wenn man sich einfach für alles, was irgendwo in Reichweite ist, vorsichtahlaber erstmal einen Mutex sichert, kommt man schnell zu Deadlocks, weil man sich eben zu viele Mutexe zusammenrafft. "Goldene Regel für Neulinge" heißt grade bei Neulingen viel zu schnell "Alles nach Schema F, Hirn aus". Grade als Neuling sollte man hier aber Hirnschmalz investieren, um rauszufinden wo man sich absichern muss und wo nicht.



  • @fdfdg:
    Ich hab' mal probiert ein paar einfache Regeln zu definieren. Ich bin nicht weit gekommen. Alleine schon die Erklärung welche Zugriffe synchronisiert werden müssen, und welche nicht. Erklär es einfach, und Anfänger haben den Eindruck dass sie bestimmte Dinge nicht synchronisieren müssen, wo es aber nötig ist. z.B. das Schreiben eines einzelnen Integers. Oder etwas ala "i++". Erklär es vollständig, und der Artikel explodiert, weil du erstmal 10 andere Begriffe erklären musst.

    Anders gesagt: das Problem ist, den Neulingen überhaupt mal klarzumachen was das Problem ist. Denn die wenigsten gesunden Programmierer suchen Lösungen für Probleme, von denen sie gar nicht wissen, dass sie sie haben.

    Wenn du meinst du kannst sowas schreiben: schreib es. Ich les es mir gerne durch, und schreib dir wo ich Probleme/Unklarheiten/... sehe.


Anmelden zum Antworten