2017-09-01 3 views
4

In einem Produkt, an dem ich gerade arbeite, wurden einige schlimme Fehler entdeckt, die allesamt auf unbeabsichtigte "Durchfälle" in Switch-Anweisungen zurückzuführen sind.Suche nach "Fallthroughs" in C-Code

Nun würde ich gerne einen Schritt weiter gehen - ich würde gerne Switch-Statement-Durchgänge in einer großen Menge von C-Code erkennen. Ich kann nur Linux und gcc 5.6 für die Kompilierung verwenden (also kein clang oder neuer gcc; dies ist, weil neuere gcc nicht für die Zielarchitektur für unser Projekt existiert).

Dies ist ein Code ohne Sturz durch:

switch(m_loadAnimSubCt){ 
     case 0: 
     case 1: 
      // Do something 
      break; 
     case 2: 
     case 3: 
     case 4: 
      // Do something 
      break; 
    } 

Dies ist ein Code mit Falldurch:

switch(m_loadAnimSubCt){ 
     case 0: 
     case 1: 
      // Do something but fall through to the other cases 
      // after doing it. 
     case 2: 
     case 3: 
     case 4: 
      // Do something else. 
      break; 
    } 
+3

Sie sollten wahrscheinlich die Begriffe * statische Analyse * und * linter * recherchieren. –

+0

Ich tat, und es sieht aus, dass Durchfälle selten abgedeckt werden. Ich weiß, dass es im neuesten gcc einen Schalter dafür gibt, aber ich kann diese Version von gcc nicht verwenden. – VividD

+4

Beide Beispiele haben "Fall-Throughs" - Fall "0" fällt auf Fall "1". In jedem Fall, wenn Sie solche Dinge entdecken wollen, schreiben Sie ein wenig Code, der Ihre Quelldatei analysiert, und schreit, wenn die gewünschten Bedingungen nicht erfüllt werden. Ein C-Compiler diagnostiziert normalerweise solche Dinge nicht, da der Code gültig ist - also schreiben Sie selbst Code. – Peter

Antwort

2

Ich würde vorschlagen, den Code mit einem neueren Compiler kompiliert, die gerade zu erkennen (I Ich weiß, dass du erwähnt hast, dass du das nicht für das Projekt tun könntest, aber es ist manchmal nützlich, es mit etwas anderem zu kompilieren, um eine andere Perspektive zu haben.

Was ich bei meiner Arbeit habe, ist eine (unheimlich) alte Version von GCC, die unseren "offiziellen" Code kompiliert und eine Dummy-Compilation macht, nur um eine bessere statische Analyse zu haben.

+0

Dies ist auch ein ziemlich vernünftiger Vorschlag, eine Dummy-Kompilierung mit einem neueren Compiler würde als externer Linter dienen. – Groo

+0

Ein neueres gcc existiert nicht für meine Zielarchitektur. 5.6 ist das neueste. @Groo – VividD

+0

@VividD Sie brauchen nicht für Ihre Zielarchitektur zu kompilieren, das ist der Punkt, da Sie nur die vom Compiler angegebenen fliegenden Informationen benötigen –

3

Wenn Sie GCC verwenden, sollten Sie die Wimplicit-fallthrough compiler option verwenden, um eine Warnung für Fallthroughs zu generieren. Sie können es alternativ in einen Fehler machen mit -Werror (dh -Werror=implicit-fallthrough für diese spezifische Warnung.

Ich ziehe -Wextra würde mit (was diese und viele andere zusätzliche Warnungen enthält), aber wenn dies einige große Erbe Code-Basis ist, es könnte erzeugen zu viel Lärm. Es ist , was Sie anstreben sollten, mit -Wextra -Wpedantic -Werror den Build zu übergeben.

Wenn Ihre Compiler-Version nicht solche Option nicht unterstützt, vielleicht können Sie Ihre eigenen regex schreiben, die alle case passen würde s nicht Präfix von einer vorherigen case-Anweisung, obwohl Sie vorsichtig sein müssen, um sicherzustellen, dass die Regex alle OC übereinstimmt Aktualitäten, unabhängig von Formatierungen/Kommentaren.

Zum Beispiel könnten Sie so etwas wie dieses (hier ist ein demo) verwenden:

(?# match any 'case' following 'break;', ':' or '{' into a non-capturing group) 
(?# then match the remaining 'case' into a named "fallthrough" group) 
(?:(break;|:|{)[\r\n\s]*case) | (?<fallthrough>case) 

So können Sie ein Perl laufen (oder Python, oder was auch immer) Skript für Ihre Ordner und Dump alle Zeilen, in denen die Die Fallthrough-Gruppe wird erfasst.

+0

Gut, aber das '-Wimplicit-Fallthrough' ist nur in der letzten Version von GCC –

+0

@BasileStarynkevitch: Du hast recht, ich habe bemerkt, dass OP gcc 5.4 verwendet. Ich nehme an, eine Regex * könnte den Trick machen, ich werde die Antwort aktualisieren, wenn ich einen freien Moment habe. – Groo