Verwendung von clock_t clock()



  • Ich möchte Zeitdifferenzen auswerten. Dabei scheue ich mich aber davor, clock() zu
    verwenden, da ich mir, nach meinem Verständnis, damit einen Fehler einbaue, da clock_t
    in seiner Größe begrenzt ist. Daher meine Frage:
    Ist es definiert, wie clock() reagiert, wenn die Programmlaufzeit größer als clock_t ist?


  • Mod

    Nein, dieses Verhalten ist streng genommen nicht definiert, da clock_t nicht zwangsläufig unsigned ist (und in der Regel auch signed sein wird) und signed-Überläufe in der Theorie undefiniert sind (in der Praxis aber meistens doch). Aber bei nichts was du tust wird dieser Fall jemals eintreten (es sei denn, dein Programm läuft ein paar Millionen Jahre). Vielleicht wäre aber eine Betriebssystemfunktion oder der neue (C++11) Header chrono etwas für dich. Was genau hast du vor, dass du Angst vor Überlaufen in clock hast?



  • Da habe ich wohl irgenwo einen Denkfehler.
    Die Hilfe von VC2008 gibt an, dass clock_t als long = 4 Bytes definiert ist. Also gibt es nach 2.147.483.637 Ticks, das wären nach meinen Überlegungen und CLOCKS_PER_SEC=1000 rd. 24 Tagen, einen Überlauf.


  • Mod

    ujt schrieb:

    Da habe ich wohl irgenwo einen Denkfehler.
    Die Hilfe von VC2008 gibt an, dass clock_t als long = 4 Bytes definiert ist. Also gibt es nach 2.147.483.637 Ticks, das wären nach meinen Überlegungen und CLOCKS_PER_SEC=1000 rd. 24 Tagen, einen Überlauf.

    Ok, dann ist dein System eben eines mit einem sehr kleinen clock_t. Ist das wirklich relevant? Was genau hast du vor, dass dies eine Rolle spielen könnte? Hat man in Windows eigentlich mittlerweile den Bug gefixt, dass das Betriebssystem nach dieser Zeit aus genau diesem Grund abstürzt?

    Wenn du uns sagst, was du erreichen möchtest, anstatt wie du es erreichen möchtest (oder hier: Wie du es nicht erreichen möchtest), dann könnte man dir übrigens viel besser helfen.



  • time(&start); fehler=0;
    while( !Daten_im_seriellen_Puffer() )
    {
     time(&messen);
     if(difftime(messen, start)) {fehler=1; break;}
    }
    

    Ich warte auf Antwort vom seriellen Port. Damit ich nicht ewig warte wenn das
    Gerät nicht antwortet habe ich die difftime-Funktion eingebaut. Nur ist eine
    Sekunde etwas zu lange gewartet. In einem Zyklus frage ich 60 Geräte ab und
    da kann sich die Zeit tüchtig summieren.



  • Das spielt bei dir keine Rolle, da dank Zweierkomplement auch die unsigned-Differenzen passen.
    Wenn dir dabei unwohl ist, kannst du ja vergleichen, ob die neue Zeit kleiner als die alte Zeit ist und dann extra behandekn.

    SeppJ schrieb:

    Hat man in Windows eigentlich mittlerweile den Bug gefixt, dass das Betriebssystem nach dieser Zeit aus genau diesem Grund abstürzt?

    Ich habe noch Windows 95 und Windows 98 Systeme, die monatelang durchlaufen.

    Bei den Programmen die darauf laufen, werden auch Zeitdifferenzen mit clock() ermittelt. Das gibt keine Probleme.



  • [quote="DirkB"]
    Wenn dir dabei unwohl ist, kannst du ja vergleichen, ob die neue Zeit kleiner als die alte Zeit ist und dann extra behandekn.
    [/quote]

    Gehst du davon aus oder weißt du, dass clock() nach Überlauf wieder bei 0 anfängt?


  • Mod

    ujt schrieb:

    Gehst du davon aus oder weißt du, dass clock() nach Überlauf wieder bei 0 anfängt?

    Nicht bei 0, aber clock_t ist (bei dir) ein signed Typ. Dies ist zwar, wie schon erwähnt, bei Überlaufen ganz streng gesehen undefiniert, aber wenn du ein System hast, auf dem Windows läuft, dann kannst du mit Sicherheit davon ausgehen, wie DirkB schon gesagt hat, dass im Zweierkomplement gerechnet wird. Das heißt, der maximale Wert + 1 ist der minimale Wert und minimaler Wert - maximaler Wert ist wie erwartet auch 1.



  • Wenn clock_t ein unsigned Integer ist, ist das sogar so im Standard definiert.

    Wenn es ein signed Integer ist, ist es zumindest unter Windows so, das ein int von INT_MAX auf INT_MIN überläuft. Der Wert wird also negativ.
    Wenn du jetzt aber (im Wertebereich von int) rechnest INT_MIN - INT_MAX ergibt das 1.
    Das gleich gilt dann für long.

    clock_t darf allerdings auch ein Fließkommatyp sein.

    In den Compilern für Windows, die ich gerade gefunden habe (VS2005, VS2008 und gcc) ist es vom Typ long.
    Ein Compiler für HP-UX hat es als unsigned long definiert.

    Die Differenz neueZeit-alteZeit gibt da eigentlich immer den richtigen Wert. (Es sei denn, die Differenz ist zu groß)



  • #include <stdio.h>
    #include <limits.h>
    
    int main()
    { int i = INT_MIN - INT_MAX;
      unsigned int ui = 0U - UINT_MAX;
    
      printf("%d - %d = %d\n", INT_MIN, INT_MAX, i);
      printf("%u - %u = %u\n", 0U, UINT_MAX, ui);
    
      return 0;
    }
    

    ergibt:

    -2147483648 - 2147483647 = 1
    0 - 4294967295 = 1
    

    Guckst du: http://codepad.org/ABvlmxKr



  • SeppJ schrieb:

    Dies ist zwar, wie schon erwähnt, bei Überlaufen ganz streng gesehen undefiniert, aber wenn du ein System hast, auf dem Windows läuft, dann kannst du mit Sicherheit davon ausgehen, wie DirkB schon gesagt hat, dass im Zweierkomplement gerechnet wird. Das heißt, der maximale Wert + 1 ist der minimale Wert und minimaler Wert - maximaler Wert ist wie erwartet auch 1.

    Problem ist halt, dass einige Compiler die Undefiniertheit des Signed-Overflows recht aggressiv ausnutzen, GCC und Clang gehören z.B. dazu. Da bringt es einem nichts, wenn die Berechnung auf Maschinenebene wohldefiniert ist, wenn die passenden Instruktionen nie generiert werden.


  • Mod

    Fischrahmsoße schrieb:

    SeppJ schrieb:

    Dies ist zwar, wie schon erwähnt, bei Überlaufen ganz streng gesehen undefiniert, aber wenn du ein System hast, auf dem Windows läuft, dann kannst du mit Sicherheit davon ausgehen, wie DirkB schon gesagt hat, dass im Zweierkomplement gerechnet wird. Das heißt, der maximale Wert + 1 ist der minimale Wert und minimaler Wert - maximaler Wert ist wie erwartet auch 1.

    Problem ist halt, dass einige Compiler die Undefiniertheit des Signed-Overflows recht aggressiv ausnutzen, GCC und Clang gehören z.B. dazu. Da bringt es einem nichts, wenn die Berechnung auf Maschinenebene wohldefiniert ist, wenn die passenden Instruktionen nie generiert werden.

    Nicht so aggressiv, dass es hier relevant werden könnte. Dazu müsste zur Compilezeit feststehen, dass ein Überlauf erfolgt. Um zur Laufzeit Überlaufe abzufangen müsste sogar zusätzlicher Code erzeugt werden, dass wird garantiert nicht passieren. GCC und CLang benutzen sowieso einen 64 Bit Typ für clock_t (zumindest auf 64-Bit Maschinen), womit wir wieder bei ein paar Millionen Jahren sind.

    edit: Die eigentliche Frage ist jedoch, ob clock hier überhaupt das richtige Mittel ist. So wie das klingt, möchte der TE doch eher Unterschiede in der Echtzeit wissen, also ein klassisches time oder das entsprechende Äquivalent aus C++11.



  • ujt schrieb:

    Die Hilfe von VC2008 gibt an, dass clock_t als long = 4 Bytes definiert ist. Also gibt es nach 2.147.483.637 Ticks, das wären nach meinen Überlegungen und CLOCKS_PER_SEC=1000 rd. 24 Tagen, einen Überlauf.

    Daraus schließe ich, dass du Windows als Plattform verwenden willst. Wenn du Plattformspezifik ausnutzen willst, helfen Standardfunktionen wie clock() wenig, probiere mal WinAPI:: GetTickCount64()
    Die Auflösung ist mit ca. 15ms annehmbar, der Überlauf sollte erst bei vielen Jahren Sessionlaufzeit auftreten.



  • *snip*



  • Vielen Dank für Eure Hilfe. Meine Lösung sieht jetzt so aus:

    start=clock(); fehler=0;
    while( !Zeichen_im_seriellen_Puffer )
    {
      messen=clock();
      if(messen < start) { start=clock(); continue; }
      if( (messen-start) > 100) {fehler=1; break;}
    }
    

    Einziger Wermutstropfen ist, dass beim Übergang von positiven zu
    negativen Zahlen die Schleife max. 0,2s durchlaufen wird. Aber da
    das ja nur einmal in 48 Tagen passiert kann ich das verschmerzen. 😉

    PS: Warum erscheint mein Quoting und mein Code nicht in so tollen
    Kästchen wie bei Euch?


  • Mod

    ujt schrieb:

    PS: Warum erscheint mein Quoting und mein Code nicht in so tollen
    Kästchen wie bei Euch?

    Hast du BBCode ausgeschaltet? Guck mal unter dem Editierfenster, unter den Smileys, unter den Formatierungsbuttons, unter den griechischen Buchstaben, da sollten Optionen für den Beitrag stehen, da gibt es eine "BBCode in diesem Beitrag deaktivieren".



  • SeppJ schrieb:

    Hast du BBCode ausgeschaltet? Guck mal unter dem Editierfenster, unter den Smileys, unter den Formatierungsbuttons, unter den griechischen Buchstaben, da sollten Optionen für den Beitrag stehen, da gibt es eine "BBCode in diesem Beitrag deaktivieren".

    Melde Vollzug! Häkchen entfernt! Danke


Anmelden zum Antworten