Globale Variablen bei großen Programmen



  • manni66 schrieb:

    Wenn die Variable ohne irgendeinen Synchronisationsmechanismus einfach nur so gesetzt wird, tritt genau der von dir beschriebene Effekt auf.

    Lösungen wären:
    Mutex
    boost::atomic
    ein von deiner Compilerimplementierung vorgesehener Mechanismus

    Keine Lösung ist volatile, es sei denn, dein Compiler will das explizit so.

    Lars

    Sag mir einen Compiler, der es nicht so will.



  • volkard schrieb:

    Roger Wilco schrieb:

    Also doch Events...?!

    Aber nicht wie bei Dir als Variable zweckentfremdet.

    kann es eben dauern, bis das nächste mal die Abfrage nach dem Abbruch-Event durchgeführt wird

    Wenn Du so programmieren willst, dann sind Events unangebracht.

    Warum als Variable zweckentfremdet? Ich würde das Event setzten, wenn der Thread abbrechen soll und sobald der Thread das Event durch WaitFor... "abfragt", dann bricht der Thread eben ab.

    Haben wir uns falsch verstanden, oder mache ich etwas grundsätzliches verkehrt? 😕

    Edit: Du meinst, wenn der Thread eh ein Event-Handler (z.B. WaitFor...) besitzt, dann würdest Du mit einem Abbruch_Event arbeiten und wenn es nur eine stupide while()/for()-Schleife ist, dann mit einer globalen Abbruch-Variable?



  • volkard schrieb:

    manni66 schrieb:

    Wenn die Variable ohne irgendeinen Synchronisationsmechanismus einfach nur so gesetzt wird, tritt genau der von dir beschriebene Effekt auf.

    Lösungen wären:
    Mutex
    boost::atomic
    ein von deiner Compilerimplementierung vorgesehener Mechanismus

    Keine Lösung ist volatile, es sei denn, dein Compiler will das explizit so.

    Lars

    Sag mir einen Compiler, der es nicht so will.

    gcc, VisualStudio

    Lars



  • manni66 schrieb:

    volkard schrieb:

    manni66 schrieb:

    Wenn die Variable ohne irgendeinen Synchronisationsmechanismus einfach nur so gesetzt wird, tritt genau der von dir beschriebene Effekt auf.

    Lösungen wären:
    Mutex
    boost::atomic
    ein von deiner Compilerimplementierung vorgesehener Mechanismus

    Keine Lösung ist volatile, es sei denn, dein Compiler will das explizit so.

    Lars

    Sag mir einen Compiler, der es nicht so will.

    gcc, VisualStudio

    Lars

    Früher hab ich globale Variablen so verwendet (viel mit MSVC) und es funktionierte. Was passiert schlimmstenfalls genau, wenn der Compiler so ist, wie Du sagst?



  • Vielen Dank für eure Antworten erstmal.

    "...grade in dem langsamen Codeabschnitt ist..."
    Das habe ich überprüft und ist nicht der Fall.

    "...irgendwo wieder zurückgesetzt..."
    Die Variable wird nirgendwo sonst zurückgesetzt/verändert.

    "...volatile..."
    Hatte ich auch bereits probiert - brachte nix.

    @manni66
    "Wenn die Variable ohne irgendeinen Synchronisationsmechanismus einfach nur so gesetzt wird, tritt genau der von dir beschriebene Effekt auf."
    Und Warum?

    Also gelöst ist das Problem noch immer nicht und ich verstehe nicht weshalb.

    Gruß
    Trooper



  • volkard schrieb:

    manni66 schrieb:

    volkard schrieb:

    manni66 schrieb:

    Wenn die Variable ohne irgendeinen Synchronisationsmechanismus einfach nur so gesetzt wird, tritt genau der von dir beschriebene Effekt auf.

    Lösungen wären:
    Mutex
    boost::atomic
    ein von deiner Compilerimplementierung vorgesehener Mechanismus

    Keine Lösung ist volatile, es sei denn, dein Compiler will das explizit so.

    Lars

    Sag mir einen Compiler, der es nicht so will.

    gcc, VisualStudio

    Lars

    Früher hab ich globale Variablen so verwendet (viel mit MSVC) und es funktionierte. Was passiert schlimmstenfalls genau, wenn der Compiler so ist, wie Du sagst?

    1. es funktioniert nicht (zuverlässig), oder schlimmer, auf Rechner A (deiner) ja, auf B (Kunde) nein
    2. da der Compiler die Zugriffe nicht optimiert, sind sie langsamer (ist im im vorliegenden Code wohl unerheblich)

    Lars



  • trooper schrieb:

    @manni66
    "Wenn die Variable ohne irgendeinen Synchronisationsmechanismus einfach nur so gesetzt wird, tritt genau der von dir beschriebene Effekt auf."
    Und Warum?

    Weil die verschiedenen Prozessorkerne bei Multicore-Architekturen jeweils eine eigene Kopie der Variablen benutzen, und über die Änderung in einem anderen Kern nicht informiert werden.

    Siehe auch: Programming with POSIX Threads, David R. Butenhof
    oder die Seite von Herb Sutter (http://www.gotw.ca/)

    Lars



  • Und der Thread endet nach längerer Zeit dann nur, weil der Thread immer wieder mal vom BS auf einen anderen Kern gelegt wird und irgendwann zufällig mal auf dem Kern landet, der die Änderung kennt?

    Der da http://www.shafqatahmed.com/2008/01/multi-core-cach.html sagt, daß das auf x86 und x64 kein Problem wäre.

    Na, wie gut, daß wie trooper zum Ausprobieren bhaben.

    @trooper: Wie willste deine atomics haben? Boost, linux oder WinAPI?



  • manni66 schrieb:

    oder die Seite von Herb Sutter (http://www.gotw.ca/)

    Solche nicht nachvollziehbaren Links kannste Dir auch sparen. Die belegen gar nichts.



  • Es ist x86 unter Windows.

    Und es klappt jetzt nur verstehe ich nicht ganz warum.
    Ich rufe eine externe Funktion auf, die als Rückgabewert diese ominöse globale Variable hat.

    for (...) {
      if (isAborted()) {
        return;
      }
    }
    


  • volkard schrieb:

    manni66 schrieb:

    oder die Seite von Herb Sutter (http://www.gotw.ca/)

    Solche nicht nachvollziehbaren Links kannste Dir auch sparen. Die belegen gar nichts.

    Wenn du meinst ...

    Lars



  • trooper schrieb:

    Es ist x86 unter Windows.

    Und es klappt jetzt nur verstehe ich nicht ganz warum.
    Ich rufe eine externe Funktion auf, die als Rückgabewert diese ominöse globale Variable hat.

    for (...) {
      if (isAborted()) {
        return;
      }
    }
    

    Hast Du zufällig eine lokale Variable isAborted oder ein Attribut isAborted hier oder der Basisklasse angelegt?
    Um nochmal auf die cache-Therie zu kommen, würde ein anderer Funktionsaufruf, sagen wir mal

    cout<<"";
    

    oder

    CloseHandle(INVALID_HANDLE_VALUE);
    

    vor dem if es auch reparieren?

    Die passenden atomics wären glaube ich

    LONG isAborted=0;//bool isAborted=false;
    InterlockedOr(&isAborted,1);//isAborted=true;
    if(InterlockedOr(&isAborted,0));//if(isAborted)
    


  • manni66 schrieb:

    volkard schrieb:

    manni66 schrieb:

    oder die Seite von Herb Sutter (http://www.gotw.ca/)

    Solche nicht nachvollziehbaren Links kannste Dir auch sparen. Die belegen gar nichts.

    Wenn du meinst ...
    Lars

    Nicht wegen Sutters Glaubwürdigkeit, sondern weil Du nicht die konkrete Unterseite nennst. Der schreibt nämlich viel.



  • So hundert Prozent verstanden habe ich dich jetzt glaube ich nicht.
    isAborted ist jetzt eine Funktion, welche als Rückgabe die globale Variable hat.

    bool isAborted(void) {
      return bAbortJob;
    }
    

    Es gibt keine andere lokale Variable bzw. Funktion, welche genauso heißt.
    Im Algorithmus werden andere Funktionen aufgerufen (die Progressbar aktualisiert etc.). Ein cout<"" ändert da nichts.



  • volkard schrieb:

    manni66 schrieb:

    volkard schrieb:

    manni66 schrieb:

    oder die Seite von Herb Sutter (http://www.gotw.ca/)

    Solche nicht nachvollziehbaren Links kannste Dir auch sparen. Die belegen gar nichts.

    Wenn du meinst ...
    Lars

    Nicht wegen Sutters Glaubwürdigkeit, sondern weil Du nicht die konkrete Unterseite nennst. Der schreibt nämlich viel.

    Ja, und das sollte man in Bezug auf Threads auch (fast) alles lesen. Mit Threads schießt man sich sonst sehr schnell ins eigene Knie. Ist halt alles nicht so einfach ...

    Lars



  • Ist im Standard nicht festgelegt, was volatile macht?



  • canthecan schrieb:

    Ist im Standard nicht festgelegt, was volatile macht?

    Es gibt im aktuellen Standard keine Aussage zu Threads, also auch nicht zum Verhalten von volatile. Genau genommen ist eine C++-Threadimplementierung wohl nicht standardkonform.

    Lars



  • Das Projekt besteht aus vielen Modulen. Meine Vermutung war zunächst, dass es an der Projektgröße liegt, denn bei kleineren Projekten trat das Problem noch nie auf. Warum es mit dem kleinen Trick nun doch geht verstehe ich erst recht nicht und das wurmt mich.



  • trooper schrieb:

    Das Projekt besteht aus vielen Modulen. Meine Vermutung war zunächst, dass es an der Projektgröße liegt, denn bei kleineren Projekten trat das Problem noch nie auf. Warum es mit dem kleinen Trick nun doch geht verstehe ich erst recht nicht und das wurmt mich.

    Vielleicht wird die Speicherseite mit Variablen drin erst durch den Funktionsaufruf geladen und enthält dann den richtigen Wert.

    Warum weigerst du dich, einen Mutex oder ähnliches einzusetzen?

    Lars



  • Vielleicht liegt die Funktion in der korrekten Übersetzungseinheit udn greif daher auf die richtige Variable zu, was bei dem direkten Zugriff nicht der Fall war. Fehlendes extern, etc...


Anmelden zum Antworten