Frage

Ich möchte alle die Orte, in meinem Code sehen (C ++), die Mißachtung Rückgabewert einer Funktion. Wie kann ich es tun - mit gcc oder statischem Code-Analyse-Tool

?

Bad Codebeispiel:

int f(int z) {
    return z + (z*2) + z/3 + z*z + 23;
}


int main()
{
  int i = 7;
  f(i); ///// <<----- here I disregard the return value

  return 1;
}

Bitte beachten Sie, dass:

  • sollte es funktionieren, auch wenn die Funktion und ihre Verwendung ist in verschiedenen Dateien
  • frei statische Überprüfung Werkzeug
War es hilfreich?

Lösung

Sie möchten GCC warn_unused_result Attribut:

#define WARN_UNUSED __attribute__((warn_unused_result))

int WARN_UNUSED f(int z) {
    return z + (z*2) + z/3 + z*z + 23;
}

int main()
{
  int i = 7;
  f(i); ///// <<----- here i disregard the return value
  return 1;
}

Mit diesem Code zu kompilieren Der Versuch erzeugt:

$ gcc test.c
test.c: In function `main':
test.c:16: warning: ignoring return value of `f', declared with
attribute warn_unused_result

Sie können diese sehen im Einsatz in der Linux-Kernel ; sie haben eine __must_check Makro, das die gleiche Sache tut; Sieht aus wie Sie benötigen GCC 3.4 oder höher für diese Arbeit. Dann werden Sie dieses Makro in Kernel-Header-Dateien verwendet finden:

unsigned long __must_check copy_to_user(void __user *to,
                                        const void *from, unsigned long n);

Andere Tipps

Soweit ich weiß gibt es keine GCC Möglichkeit, diese Warnung zu geben. Wenn Sie jedoch in bestimmten Funktionen interessiert sind, können Sie diese mit einem Attribut-Tag:

int fn() __attribute__((warn_unused_result));

, die eine Warnung geben würden, wenn der Rückgabewert von fn () nicht verwendet wurde. Caveat:. Ich habe noch nie um diese Funktion nutzen selbst verwendet

Sie können diese handliche Vorlage verwenden es zur Laufzeit zu tun.

Statt einen Fehlercode zurückkehrt (z HRESULT) Sie einen rückkehr zurück, die behauptet, wenn es sein Lese ohne den Wert des Bereichs erlischt. Es ist nicht ein statisches Analyse-Tool, aber es ist nützlich, nicht weniger.

class return_value
{
public:
  explicit return_value(T value)
    :value(value), checked(false)
  {
  }

  return_value(const return_value& other)
    :value(other.value), checked(other.checked)
  {
    other.checked = true;
  }

  return_value& operator=(const return_value& other)
  {
    if( this != &other ) 
    {
      assert(checked);
      value = other.value;
      checked = other.checked;
      other.checked = true;
    }
  }

  ~return_value(const return_value& other)
  {
    assert(checked);
  }

  T get_value()const {
    checked = true;
    return value;
  }

private:
  mutable bool checked;
  T value;
};

Für C ++ 17 die Antwort auf diese Frage ändert, da wir jetzt die [[nodiscard]] Attribut. Covered in [dcl.attr.nodiscard] :

  

Das Attribut-Token nodiscard kann in einer Funktionsdeklaration oder die Deklaration einer Klasse oder Aufzählung der declarator-ID angewandt werden. Es wird höchstens erscheinen einmal in jeder Attribut-Liste und keine Attribut-Argument-Klausel muss vorhanden sein.

und

  

[Beispiel:

struct [[nodiscard]] error_info { /* ... */ };
error_info enable_missile_safety_mode();
void launch_missiles();
void test_missiles() {
  enable_missile_safety_mode(); // warning encouraged
  launch_missiles();
}
error_info &foo();
void f() { foo(); }             // warning not encouraged: not a nodiscard call, because neither
                                // the (reference) return type nor the function is declared nodiscard
     

- Ende Beispiel]

Ihr Beispiel So Modifizieren ( sieht es Live ):

[[nodiscard]] int f(int z) {
    return z + (z*2) + z/3 + z*z + 23;
}


int main()
{
  int i = 7;
  f(i); // now we obtain a diagnostic

  return 1;
}

Wir erhalten nun eine Diagnose sowohl mit gcc und Klirren z.

warning: ignoring return value of function declared with 'nodiscard' attribute [-Wunused-result]
  f(i); // now we obtain a diagnostic
  ^ ~

Jeder statischen Analysecode (zum Beispiel PC-Lint ) sollte in der Lage sein, dies zu sagen. Für PC-Lint, weiß ich, dass dies der Fall ist.

ein statischer Analysator wird die Arbeit für Sie, aber wenn Ihre Code-Basis mehr als trivial vorbereiten überwältigt werden ist; -)

Ein statischer Analysator wird hier die beste Wahl sein. Wir verwenden Coverity hier, aber es gibt kostenlose Tools zur Verfügung, die Sie auch nutzen können.

Wenn Sie eine schnelle und unsaubere Lösung und Sie haben ein Linux-basiertes Handy Shell, können Sie versuchen, so etwas wie:

grep -rn "function_name" * | grep -v "="

Das wird jede Zeile, dass Verweise der angegebene Funktion finden, aber keine „=“ enthalten. Sie können eine Menge Fehlalarme auslösen (und möglicherweise einige falsche Negative), aber wenn Sie keine statische Analysator haben, ist es ein ordentliches Hotel zu starten.

Das Programm klassische ‚Fussel‘ verwendet, sehr redselig über Funktionen, die einen Wert zurückgeführt, die ignoriert wurde. Das Problem war, viele dieser Warnungen unerwünscht waren - was zu einer übermäßigen Lärm in der Fussel-Ausgang (es wurde Flusen Aufnehmen, dass Sie es ignorieren wollte). Das ist wahrscheinlich, warum GCC keinen Standard Warnung für sie.

Das andere Problem - die Kehrseite - ist „wie unterdrücken Sie die Warnung, wenn Sie wissen, dass Sie das Ergebnis ignorieren aber wirklich nicht egal“. Das klassische Szenario für das heißt:

if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
    signal(SIGHUP, sighandler);

Sie kümmern sich um das erste Ergebnis aus signal(); Sie wissen, dass die zweite SIG_IGN sein wird (da Sie es nur, dass festgelegt). Um von den Warnungen entfernt, habe ich manchmal eine Variante verwenden auf:

if ((old = signal(SIGHUP, SIG_IGN)) != SIG_IGN)
    old = signal(SIGHUP, sighandler);

Ordnet beiden Male old. Sie können, dass folgen mit 'assert (alt == SIG_IGN)'.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top