Gibt es eine Möglichkeit, Warnungen für Funktionszeigervergleiche zu generieren?

Lesezeit: 3 Minuten

Benutzer-Avatar
Benutzer541686

Ich habe ewig gebraucht, um herauszufinden, dass es einen Fehler in meinem Code gab, der ausgelöst wurde /OPT:ICF:

Da /OPT:ICF kann dazu führen, dass dieselbe Adresse verschiedenen Funktionen oder schreibgeschützten Datenelementen zugewiesen wird (const-Variablen, die mit /Gy kompiliert wurden), kann ein Programm beschädigt werden, das von eindeutigen Adressen für Funktionen oder schreibgeschützten Datenmembern abhängt.

(Ich hatte Funktionszeiger auf Gleichheit gespeichert und verglichen, was bricht, wenn der Linker identische Funktionen wegwirft.)

Jetzt muss ich jeden Ort finden, an dem ich so etwas hätte tun können.

Der Testfall ist natürlich trivial:

//MSVC: /Gy /link /OPT:ICF
int test1(void) { return 0; }
int test2(void) { return 0; }
int main(void) { return test1 == test2; }

ich habe es versucht -Wall, -Wextra, -Weverything, -pedanticusw., aber keiner von ihnen generiert Warnungen.

Gibt es irgendein Compileroption oder Tool (ob Teil von Visual C++, GCC, Clang oder anderem), das meinen Code analysieren und mir sagen kann, wo ich Funktionszeiger miteinander vergleiche, wie im obigen Code?

  • @DrewDormann: Ja. Ich bin ehrlich gesagt verblüfft, dass es nicht schon einen zu geben scheint, soweit ich sehen kann.

    – Benutzer541686

    29. Januar 2018 um 5:19 Uhr


  • @BenjaminBarrois: Wenn Sie fragen möchten, “warum sollte jemand jemals daran denken, Funktionszeiger zu vergleichen”, dann posten Sie es als separate Frage und zögern Sie nicht, mich anzupingen, und ich werde gerne eine Antwort posten. Es ist hier jedoch nicht relevant; Ich versuche, sie aus meinem Code zu entfernen, nicht sie hinzuzufügen.

    – Benutzer541686

    29. Januar 2018 um 6:25 Uhr

  • @DeanSeo: Haha, danke. Es dauerte Stunden, und das war mit mein Wissen wovon /OPT:ICF tut. Mir war nur nicht klar, dass es der Übeltäter sein könnte, weil ich nicht dachte, dass ich irgendwo Funktionszeiger vergleiche, also dauerte es ewig, bis mir klar wurde, dass ich versuchen sollte, es umzuschalten (und danach war es “nur” der Schmerz, die Code). Ich kann mir nicht vorstellen, was eine andere arme Seele, die nichts über das Verhalten der Flagge weiß, durchmachen muss, um es herauszufinden …

    – Benutzer541686

    29. Januar 2018 um 7:47 Uhr


  • @AjayBrahmakshatriya: Nein, kein Duplikat. Diese spezielle Frage (Warnungen generieren) befasst sich mit Gegenmaßnahmen, während die verknüpfte Frage nach Ursachen spricht.

    – MSalter

    29. Januar 2018 um 15:37 Uhr

  • @ShafikYaghmour: MSVC++ ist perfekt konform /OPT:NOICF das ist die Voreinstellung; Sie können Microsoft nicht dafür verantwortlich machen, dass es eine schnelle, aber gefährliche Option hinzugefügt hat. Dasselbe gilt für schnelle Fließkomma-Mathematik – wenn Sie den Kompromiss nicht verstehen, bleiben Sie bei der sicheren Standardeinstellung.

    – MSalter

    29. Januar 2018 um 17:35 Uhr

Benutzer-Avatar
Barry

Gibt es eine Compileroption oder ein Tool (ob Teil von Visual C++, GCC, Clang oder anderem), das meinen Code analysieren und mir sagen kann, wo ich Funktionszeiger miteinander vergleiche, wie im obigen Code?

Ich bin mir nicht sicher, ob es eine solche Compiler-Option gibt.

Es gibt jedoch ein solches Tool. klang-ordentlich. Sie können Ihre eigenen Schecks für clang-tidy schreiben, es ist eigentlich bemerkenswert einfach, wenn Sie folgen dieses Blog. Insbesondere enthält der AST bereits eine Reihe von Matchern, die den gewünschten Anwendungsfall bewältigen sollten.

So etwas scheint zu funktionieren:

binaryOperator(
    anyOf(hasOperatorName("=="), hasOperatorName("!=")),
    hasLHS(ignoringImpCasts(declRefExpr(hasType(functionType())))),
    hasRHS(ignoringImpCasts(declRefExpr(hasType(functionType())))))

Was das Beispiel im OP kennzeichnet:

fp.cxx:3:25: note: "root" binds here
int main(void) { return test1 == test2; }
                        ^~~~~~~~~~~~~~

Das funktioniert speziell für den OP-Fall, aber Sie müssen tatsächlich expliziter sein, um alle anderen wahrscheinlichen Fälle abzugleichen:

const auto AnyFunc = ignoringImpCasts(declRefExpr(hasType(anyOf(
    functionType(),
    pointsTo(functionType()),
    references(functionType())))));

Finder->AddMatcher(binaryOperator(
    anyOf(hasOperatorName("=="), hasOperatorName("!=")),
    hasLHS(AnyFunc),
    hasRHS(AnyFunc)).bind("op"), this);

Oder etwas in der Nähe dieses Effekts.

  • Heilige Kuh, das war mir gerade nicht klar wie einfach war es, dies zu tun. Ich werde es bei Gelegenheit ausprobieren; Danke!!

    – Benutzer541686

    30. Januar 2018 um 18:35 Uhr

1370180cookie-checkGibt es eine Möglichkeit, Warnungen für Funktionszeigervergleiche zu generieren?

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

Privacy policy