Fangen Sie die falsche Verwendung von c bool ab

Lesezeit: 5 Minuten

Benutzer-Avatar
Plaisthos

In einem C-Projekt (OpenVPN ist das betreffende Projekt, commit 4029971240b6274b9b30e76ff74c7f689d7d9750) hatten wir eine Emulation von bool

typedef int bool;
#define false 0
#define true 1

und wechseln Sie jetzt zu C99 bool

#include <stdbool.h>

Aber in dem Projekt gibt es irgendwo eine schlechte Verwendung des bool. Ich weiß, dass sich der std bool anders verhält. Z.B

bool t;

t=2;
if ( t == true)
    printf("True!\n");
else
    printf("False!\n");

Wird True zurückgeben! mit stdbool.h und falsch! mit dem #define Emulation.

Meine Frage Gibt es eine Möglichkeit, diese Codeteile zu finden, die sich mit stdbool und dem emulierten Bool anders verhalten? Vielleicht ein Compiler-Flag, das ich übersehen habe, oder ein gutes llvm- oder gcc-Zwischenformat, das unterschieden werden kann?

Es ist nicht so einfach wie im obigen Beispiel, aber es muss etwas sein, das nicht so leicht zu sehen ist. Definitiv kein == wahr.

AKTUALISIEREN:
Wir haben das Problem gefunden (mbuf_set hat ein int-Member len). Es ist irgendwie dumm, aber die Frage bleibt immer noch, wie man diese fängt. Ich bin überrascht, dass die Integer-Überlaufprüfungen solche Dinge nicht abfangen:

 static inline bool
 mbuf_len (const struct mbuf_set *ms)
 {
   return ms->len;
 }

  • Suchen Sie einfach nach den Bool-Literalen; Code, der verglichen wird true oder false wird buchstäblich ein Problem haben. Code mit der (besseren, imo) Art, es einfach zu sagen if( t ) wird in Ordnung sein. Du könntest vielleicht suchen true|false und filtern Sie das dann nach Treffern für ==.

    – abschalten

    11. März 2013 um 12:58 Uhr

  • Eine Möglichkeit besteht darin, eine Aufzählung anstelle von Definitionen zu verwenden. Lassen Sie dann einen statischen Codeanalysator Ihren Code parsen und auf Fehler wie „t=2“ prüfen. Aber das würde jeden Code ergeben, auch Sachen wie “t=1”.

    – Argemann

    11. März 2013 um 12:59 Uhr

  • versuchen, Funktion zu schreiben getTrue und getFalse die die Anzahl der Anrufe zurückgibt. danach könnten Sie wie numberGetTrue == Menge suchen true oder nicht.

    – Dmitri Zagorulkin

    11. März 2013 um 13:23 Uhr


  • Wenn Sie mit einem C++-Compiler kompilieren können, versuchen Sie, eine Klasse check_bool zu erstellen, die eine implizite Umwandlung in bool hat. Operator == überschreiben, Operator = (für int privat machen, für check_bool öffentlich machen). Dann #define bool check_bool. Definieren Sie auch true und false für Objekte dieser Klasse.

    – Aneri

    11. März 2013 um 13:35 Uhr


  • Ich weiß, dass es nicht C++ ist, aber C kann manchmal von einem C++-Compiler kompiliert werden. Dies ist eine Testkompilierung, um zu sehen, wo int zugewiesen/mit Werten von bool verglichen wird.

    – Aneri

    11. März 2013 um 13:45 Uhr

Benutzer-Avatar
teppisch

Die Art der Verwendung, die Sie beschreiben, ist ein korrektes, gut definiertes Verhalten. Der Compiler wird also keine Warnungen erzeugen. Eine Möglichkeit, dies zu umgehen, besteht darin, die zu ändern typedef:

typedef enum {false, true} bool;

Dadurch kann der Code immer noch fehlerfrei kompiliert werden (da er gut definiert ist), aber Sie können möglicherweise Warnungen von einem Compiler oder Analysator erzwingen. Zum Beispiel, clang werde so etwas mit abholen -Weverything:

$ clang -o a a.c -Weverything
a.c:7:11: warning: integer constant not in range of enumerated type 'bool'
      [-Wassign-enum]
        bool n = 2;

Dies führt natürlich keine Laufzeitprüfung durch. Es wird immer noch die zulassen typedef bool-Variable, die auf etwas anderes als 0 oder 1 geändert werden soll (z. B. über einen Funktionsaufruf oder in einem Ausdruck). Die einzige Möglichkeit, diese Instanzen zu erkennen, ist die Verwendung eines Debuggers.

Die Makros für true und false in stdbool.h sind eigentlich nur für die ausgelegt _Bool Typ. Dies liegt daran, dass dieser Typ nur die Werte 0 und 1 enthalten kann; Jeder von Ihnen zugewiesene Wert, der nicht 0 ist, wird als 1 gespeichert. Daher funktionieren die Makros true und false nur für einen booleschen Typ garantiert.

Ohne das _Bool Typ, es gibt keine Möglichkeit, die Sprache selbst dies direkt für Sie tun zu lassen, da es keinen vergleichbaren Typ gibt, und Sie würden sie effektiv bitten, dies zuzulassen 2 == 1 gibt wahr zurück.

Es gibt ein paar Möglichkeiten, dasselbe Verhalten zu implementieren, zB mit einem Makro wie BOOL(n) in jedem Fall der Verwendung der Variablen n, um sicherzustellen, dass sein Wert nur 0 oder 1 ist. Auf diese Weise erhalten Sie das gleiche Ergebnis, unabhängig davon, ob Sie verwenden _Bool oder ein int zum n. Zum Beispiel:

#define BOOL(n) ((n) != 0 ? 1 : 0 )

bool b = rand() % 100;

if (BOOL(b) == true) ...

Dies würde funktionieren, ob mit stdbool oder ein typedef.

  • Ich weiß, dass sich die Logik geändert hat. Ich möchte keine neuen Bools emulieren. Ich möchte herausfinden, warum der Code nicht mit stdbool funktioniert

    – Plaisthos

    11. März 2013 um 13:54 Uhr

  • @plaistos Weil ohne stdbool, if ( t == true) ist das gleiche wie if ( 2 == 1).

    – teppisch

    11. März 2013 um 13:56 Uhr


  • Bitte lesen Sie meine Frage noch einmal. Mein Beispiel soll nur zeigen, dass Logik anders ist

    – Plaisthos

    11. März 2013 um 13:57 Uhr

  • @plaistos – das gleiche gilt für jeden Fall wo t ist nicht gleich 1. Die Logik ist nicht anders, es ist nur so _Bool kann nichts anderes als 0 oder 1 sein.

    – teppisch

    11. März 2013 um 13:59 Uhr

  • Ich möchte nicht das gleiche Verhalten implementieren. Ich möchte die Codeteile finden, die sich aufgrund des unterschiedlichen Verhaltens unterschiedlich verhalten. Das Hinzufügen eines #define BOOL hilft mir nicht, da ich jedes ändern müsste, wenn es sich um eine bool-Variable handelt.

    – Plaisthos

    11. März 2013 um 14:02 Uhr

1228270cookie-checkFangen Sie die falsche Verwendung von c bool ab

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

Privacy policy