Was bedeutet behaupten(0)?

Lesezeit: 6 Minuten

Benutzeravatar von Smith Western
Schmied Western

Ich hatte eine Frage wie diese in einer meiner Prüfungen und bin mir immer noch nicht sicher, wie ich darauf antworten soll. Ich verstehe, dass Behauptungen Möglichkeiten sind, Ihr Programm zu testen, aber ich bin mir nicht sicher, was assert(0) prüft. Ist das eine Fangfrage? Es wird immer scheitern, aber ich verstehe nicht warum. Was wird überprüft?

Eine Erklärung wäre toll, danke.

  • Verwenden Sie mehr Ausrufezeichen: assert(!!!”Das, was Sie gehofft haben, würde nicht passieren. Es ist einfach passiert”);

    – Hans Passant

    12. Dezember 2015 um 7:37 Uhr

  • Achten Sie nur darauf, eine ungerade Anzahl davon zu verwenden. Und in Anbetracht von Terry Pratchetts beiläufiger Bemerkung: „Mehrere Ausrufezeichen“, fuhr er kopfschüttelnd fort, „sind ein sicheres Zeichen für einen kranken Geist“, und dass 3 Ausrufezeichen sicherlich „mehrere“ sind, ist die einzige Lösung genau 1 .. Jedenfalls erinnere ich mich, dass Andrej Alexandrescu und ich uns nicht auf den besten Weg geeinigt haben. Andrei bevorzugt assert( "Blah" && condition ) während ich favorisierte assert(("Blah", condition)) (Keiner von uns mochte das Ausrufezeichen). Heute benutze ich &&weil es einfacher, mehr grokable. Aber deswegen habe ich dann favorisiert (())

    – Prost und hth. – Alf

    12. Dezember 2015 um 7:42 Uhr


Prost und hth.  - Alfs Benutzeravatar
Prost und hth. – Alf

Der C++-Standard verschiebt die Definition von assert nach C-Norm.

C99 §7.2/2:

Das assert Makro fügt diagnostische Tests in Programme ein; es erweitert sich zu einem leeren Ausdruck. Wenn es ausgeführt wird, wenn Ausdruck (das einen skalaren Typ haben soll) falsch ist (d. h. gleich 0 vergleicht), schreibt das Assert-Makro Informationen über den bestimmten Aufruf, der fehlgeschlagen ist (einschließlich des Texts des Arguments, des Namens der Quelldatei, der Nummer der Quellzeile). , und der Name der einschließenden Funktion – letztere sind jeweils die Werte der Vorverarbeitungsmakros __FILE__ und __LINE__ und der Kennung __func__) in der Standardfehlerdatei in einem implementierungsdefinierten Format. Es ruft dann die abort Funktion.


Im assert(0) das 0 wird interpretiert als falsealso wird diese Behauptung immer scheitern, oder Feuerwenn die Assertionsprüfung aktiviert ist.

Damit behauptet sie das

„Die Hinrichtung wird diesen Punkt niemals erreichen.“

In der Praxis kann es schwierig sein, Compiler zum Schweigen zu bringen, wenn die Ausführung einen bestimmten Punkt erreicht oder nicht erreicht. Oft beschwert sich der Compiler zuerst darüber, dass die Ausführung möglicherweise das Ende einer Funktion erreicht, ohne einen Wert zurückzugeben. Hinzufügen eines assert(0) Dort sollte das Problem idealerweise gelöst werden, aber dann kann sich der Compiler darüber beschweren assertoder nicht erkennen, dass Sie bereits wissen, wovor es warnen möchte.

Einer (1)Eine mögliche Maßnahme besteht dann darin, an dieser Stelle auch eine Ausnahme auszulösen:

auto foo( int x )
    -> int
{
    if( x == 1 ) { return 42; }
    assert( 0 ); throw 0;       // Should never get here!
}

Natürlich kann dieser Doppelschlag als Makro auf höherer Ebene definiert werden. In Bezug auf den Ausnahmetyp möchten Sie ihn möglicherweise auf not a belassen std::exceptionweil dies keine Ausnahme ist, die von einem gewöhnlichen gefangen werden soll catch irgendwo. Oder, wenn Sie der Standard-Ausnahmehierarchie vertrauen (es ergibt für mich keinen Sinn, aber), können Sie a verwenden std::logic_error.


Ausschalten assert Assertion Checking können Sie das Symbol definieren NDEBUG vor dem Einschließen <assert.h>.

Dieser Header hat eine spezielle Unterstützung, sodass Sie ihn mehrmals mit oder ohne einfügen können NDEBUG definiert.

C++11 §17.6.2.2/2:

Eine Übersetzungseinheit kann Bibliothekskopfzeilen in beliebiger Reihenfolge enthalten (Abschnitt 2). Jedes kann mehr als einmal enthalten sein, ohne dass sich die Wirkung von genau einer Aufnahme unterscheidet, mit der Ausnahme, dass die Auswirkung des Einfügens von einem von beiden ist <cassert> oder <assert.h> hängt jeweils von der lexikalisch aktuellen Definition von ab NDEBUG.

Eine vernünftige Definition des oben diskutierten Doppelschlags kann ebenfalls davon abhängen NDEBUG ohne Include-Wächter, zB

Datei assert_should_never_get_here.hpp

#include <stdexcept>        // std::logic_error
#include <assert.h>

#undef ASSERT_SHOULD_NEVER_GET_HERE
#ifdef NDEBUG
#   define ASSERT_SHOULD_NEVER_GET_HERE() \
        throw std::logic_error( "Reached a supposed unreachable point" )
#else
#   define ASSERT_SHOULD_NEVER_GET_HERE() \
        do{ \
            assert( "Reached a supposed unreachable point" && 0 ); \
            throw 0; \
        } while( 0 )
#endif

Haftungsausschluss: Während ich das Anfang der 2000er Jahre mehrmals codiert habe, habe ich den obigen Code nur für diese Antwort erfunden, und obwohl ich ihn mit g ++ getestet habe, ist er möglicherweise nicht unbedingt perfekt.



(1) Siehe die Antwort von Basile Starynkevitch zur Diskussion einer anderen Möglichkeit, der g++-spezifischen Intrinsic __builtin_unreachable.

  • Sehr gut zu bemerken, dass Assert deaktiviert werden kann: Ihr Codefluss sollte derselbe sein, unabhängig davon, ob es Assert gibt oder nicht!

    – edmz

    12. Dezember 2015 um 7:44 Uhr

Benutzeravatar von djechlin
Djechlin

Es wird immer scheitern. Das wars so ziemlich. Es wird immer aus demselben Grund fehlschlagen, aus dem “assert(x == 5)” erfolgreich ist, wenn x = 5 ist.

Wenn Sie nach einem fragen Anwendung dann würden Sie es in Codeblöcke stecken, die wirklich nicht passieren sollten.

switch(suit) {
  case CLUB:
  case DIAMOND:
  case HEART:
  case SPADE:
  // ...
  default:
    assert(0);
 }

  • Aber normalerweise ist eine Behauptung eine Bedingung, richtig? Was bedeutet es also, wenn dort nur “0” steht?

    – Smith Western

    12. Dezember 2015 um 5:34 Uhr

  • @SmithWestern Null ist eine Bedingung, die immer falsch ist, genau wie “die Zeit jetzt ist genau jetzt” eine Bedingung ist, die immer wahr ist.

    – Djechlin

    12. Dezember 2015 um 5:34 Uhr

  • Das sollte “wann immer x != 5” sein

    – Benutzer253751

    12. Dezember 2015 um 5:49 Uhr

  • @SmithWestern Was tut if(0) printf("Hello"); else printf("Goodbye"); tun?

    – Benutzer253751

    12. Dezember 2015 um 5:49 Uhr

  • @SmithWestern Es gibt keinen booleschen Typ in C, also haben Sie Null für “falsch” und jeden Wert ungleich Null für “wahr”.

    – Tonytonie

    12. Dezember 2015 um 6:23 Uhr

Benutzeravatar von emlai
Emlai

Ja, es wird immer scheitern.

assert(0) oder assert(false) wird normalerweise zum Markieren verwendet unerreichbarer Codesodass im Debug-Modus eine Diagnosemeldung ausgegeben und das Programm abgebrochen wird, wenn das vermeintlich Unerreichbare tatsächlich erreicht ist, was ein klares Signal dafür ist, dass das Programm nicht das tut, was wir denken.

  • Nicht “unerreichbar”, sondern “nur unerreichbar, wenn ein Fehler in meinem Code ist”. Nicht erreichbarer Code kann nicht erreicht werden. “Nur unerreichbar, wenn ein Fehler in meinem Code ist” wird viel zu oft erreicht 🙁

    – gnasher729

    12. Dezember 2015 um 14:34 Uhr

Benutzeravatar von Basile Starynkevitch
Basile Starynkevitch

Im Zusatz zu anderen Antworten (insbesondere dieser), wenn Sie eine aktuelle verwenden GCC (oder Klirren), könnten Sie erwägen, einige zu verwenden GCC eingebautvor allem __builtin_unreachable() Anstatt von assert(0).

Es gibt einige Unterschiede: Erstens assert kann mit deaktiviert werden -DNDEBUG. Und __builtin_unreachable ändert die Art und Weise, wie der Compiler Ihren Code optimiert.

Natürlich wissen einige Compiler nichts davon __builtin_unreachable.

Und Sie könnten auch erwägen, einige anzurufen [[noreturn]] C++-Funktion (in C++11 oder besser) – oder __attribute__((noreturn)) zum GCCwie zum Beispiel abort()

Übrigens, assert(0) ist nicht genau wie das Auslösen einer Ausnahme (da Ausnahmen abgefangen werden können)

1389560cookie-checkWas bedeutet behaupten(0)?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy