Hallo zusammen, gestern habe ich die Werbebrochüre für ein Werkzeug zur statischen Codeanalyse bekommen und ich frage mich, ob soetwas auch für den Hobbybereich mit vertretbarem Aufwand einsetzbar ist - zumal mir ein ähnliches Werkzeug in Fortran und Matlab schon viel geholfen hat. Ich selbst nutze den AVR-GCC (unter Atmel Studio) und den ARM-GCC (unter CooCox). Splint scheint seit 2007 verlassen zu sein. PC-Lint ist ein Werkzeug für 390USD (vielleicht nicht gerade angebracht für die ersten Versuche). Polyspace scheint im oberen Preissegment angesiedelt zu sein. Gibt es irgendein Werkzeug, bei dem die Einstiegshürde nicht zu hoch ist? Problematisch ist ja, daß so ein Werkzeug gerade dem besonders hilft, für den die Einrichtung eine große Hürde ist. Viele Grüße W.T.
Wikipedia hat eine ganze Liste von solchen Tools. Nicht alle davon sind frei verfügbar, aber einige doch: http://en.wikipedia.org/wiki/List_of_tools_for_static_code_analysis#C.2FC.2B.2B
Mark Brandis schrieb: > Wikipedia hat eine ganze Liste von solchen Tools Du hast das Problem auf den Punkt gebracht: Es ist eine sehr lange Liste von Werkzeugen. Zuviele, um sie alle anzuschauen, um die beste Lösung zu finden.
cppcheck ist ne feine sache, sowie llvm. Auch interessant für spezielle Bugs http://css.csail.mit.edu/stack/
cppcheck importiert bei mir nur ein drittel der Dateien ein. Woran kann das liegen? System ist Windows 7 64bit, volle Adminrechte. Am Dateinamen kann es nicht liegen, z.B.: PROTOCOL_RX.C wird importiert, PROTOCOL_TX.C hingegen nicht. Schade, das Tool sah viel versprechend aus.
Walter Tarpan schrieb: > Du hast das Problem auf den Punkt gebracht: Es ist eine sehr lange Liste > von Werkzeugen. Zuviele, um sie alle anzuschauen, um die beste Lösung zu > finden. "Die beste Lösung" wird man wohl kaum finden können, ohne einen gewissen Aufwand zu betreiben. Da kann man auch verlangen, dass einem die gebratenen Tauben in den Mund fliegen sollen. ;-)
Hmm....cppcheck scheint ja nicht so dolle zu sein. Hier hat es beispielsweise nichts auszusetzen:
1 | uint8_t * test(void) { |
2 | int i = 0; |
3 | static unsigned char w[] = "hallo"; |
4 | |
5 | a=b; |
6 | |
7 | for (i=0;i<6;i++) |
8 | w[i] = i+300; |
9 | |
10 | return &w; |
11 | }
|
Außerdem stürzt die Oberfläche ab, wenn die Sprache "deutsch" ist und das Einstellungsmenü verlassen wird.
Mark Brandis schrieb: > Da kann man auch verlangen, dass einem die > gebratenen Tauben in den Mund fliegen sollen. Nein, verlangen kann man nichts. Aber man kann hoffen, daß in einem Werkzeugforum Menschen gerne Tipps geben, welches Werkzeug sie benutzen. Aber scheinbar wird hier so ein Werkzeug nicht gerne oder nicht oft benutzt. Viele Grüße W.T.
Walter Tarpan schrieb: > scheint ja nicht so dolle zu sein Walter Tarpan schrieb: > Aber scheinbar wird hier so ein Werkzeug nicht gerne oder nicht oft > benutzt Scheinbar gibt es da einen Zusammenhang... Oliver
Oliver S. schrieb: > Walter Tarpan schrieb: > scheint ja nicht so dolle zu sein > > Walter Tarpan schrieb: > Aber scheinbar wird hier so ein Werkzeug nicht gerne oder nicht oft > benutzt > > Scheinbar gibt es da einen Zusammenhang... > > Oliver Mitnichten. Du willst damit wohl suggerieren dass das Werkzeug "statische Codeanalyse" hier nicht oft benutzt wird weil es nicht so toll wär. Ich würde sagen, es wird hier nicht oft benutzt weil viele schlicht nicht wissen dass es sowas gibt, oder einfach drauf sch... @Topic: splint hat bei mir mal ganz gut geklappt. Wenn das natürlich nicht mehr weiterentwickelt wird wär das schade. Du musst dir auf jeden Fall Zeit nehmen das Teil einzurichten. Ansonsten wirst du mit Warnungen überhäuft ;-)
Ben schrieb: > @Topic: splint hat bei mir mal ganz gut geklappt. Wenn das natürlich > nicht mehr weiterentwickelt wird wär das schade. Die letzte Änderung wird auf den 12. Juli 2007 datiert, das Sourceforge-Repository existiert nicht (mehr?). http://www.splint.org/changes.html Also vermutlich mal wieder ein schönes Projekt, das verwaist ist.
Walter Tarpan schrieb: > Also vermutlich mal wieder ein schönes Projekt, das verwaist ist. Wohl eher vom Lauf der Zeit überrollt. Aktuelle C/C++-Compiler erkennen inzwischen selber einen Großteil der Fehler, für die lint und Konsorten ursprünglich erdacht wurden. Oliver
PC-Lint ist schon zu empfehlen. Es erkennt viele Dinge über die der ARM-Keil-Compiler der eigentlich ein guter ist (kommt direkt von ARM) hinwegsieht. Hinzu kommt sein Fast-Alleinstellungsmerkmal wenn man auf C++ abzielt.
Walter Tarpan schrieb: > Aber scheinbar wird hier so ein Werkzeug nicht gerne oder nicht oft > benutzt. Im Beruf wird das durchaus genutzt, aber da stellt in der Regel die Firma ein (kommerzielles) Tool bereit. Privat verlasse ich mich zugegeben gerne auf "-Wall -Wextra" bei den Compiler-Einstellungen, wenn es um C bzw. C++ geht und auch ansonsten arbeite ich penibel sämtliche Warnungen ab, die mir irgendein Compiler (z.B. javac) an der Kopf wirft. Meistens reicht das.
Mark Brandis schrieb: > Im Beruf wird das durchaus genutzt, aber da stellt in der Regel die > Firma ein (kommerzielles) Tool bereit. Ich kenne genug Entwickler, die sowas gar nicht kennen. Da kommen dann schnell solche Sprüche: "sowas braucht man doch nicht..." "du kannst wohl nicht richtig programmieren..." "das macht alles der Compiler..." "sowas ist nur Geldmacherei..." Und nein diese Personen sind nicht Ü50! Gerade junge Leute lernen sowas im Studium gar nicht mehr kennen. Wenn ich dann noch sage, dass ich einen Debugger / Emulator im Büro stehen habe und diese Dinge auch noch nutze oh je oh je. Bei knapp 520€ für PC-Lint mit graphischer Oberfläche konnte sich das mein Arbeitgeber gerade so leisten ;-)
Mark Brandis schrieb: > Im Beruf wird das durchaus genutzt, aber da stellt in der Regel die > Firma ein (kommerzielles) Tool bereit. Soetwas hatte ich schon befürchtet. PC-Lint ist für den kommerziellen Einsatz wirklich als preisgünstig anzusehen- allerdings scheint es keine educational-Version zu geben. Cppcheck hat in meinem (für mich) riesigen Projektbaum gerade mal einen einizgen erstzunehmenden Fehler gefunden:
1 | static uint8_t rampe(int16_t diff) { |
2 | //diff > 0
|
3 | //gl_iVel Geschwindigkeitsindex
|
4 | int8_t aiv; // Absolutwert Geschwindigkeitsindex |
5 | |
6 | if (diff>gl_iVel) { // Bei grosser Distanz beschleunigen |
7 | gl_iVel++; |
8 | if (gl_iVel == N_RAMPSTEPS) gl_iVel = N_RAMPSTEPS-1; |
9 | }
|
10 | else if (diff>gl_iVel) { // Wenn Distanz kleiner bremsen |
11 | gl_iVel--; |
12 | if (gl_iVel == -N_RAMPSTEPS) gl_iVel = -N_RAMPSTEPS+1; |
13 | }
|
14 | |
15 | aiv = gl_iVel<0 ? -gl_iVel : gl_iVel; |
16 | return ramp[aiv]; |
17 | }
|
und ist damit für mich nicht mehr ernstzunehmen (wobei ich froh bin, den Fehler gezeigt bekommen zu haben, bevor ich die Auswirkungen bemerken konnte). -Wall, -Wextra und -Wpedantic gehören für mich zur Standardausstattung (wobei mmir letzteres wegen einiger selbst-definierter Escapcesequenzen manchmal auf den Geist geht). Den Logik-Fehler oben hat mir aber keiner gemeldet.
Walter Tarpan schrieb: > Cppcheck hat in meinem (für mich) riesigen Projektbaum gerade mal einen > einizgen erstzunehmenden Fehler gefunden: So gehts mit auch. Ich hab mein aktuelles Hobbyprojekt mal duchgeschoben (ca. je 50 Source- und Header-Dateien), und zwei "Probleme" gefunden. Das eine hatte schon ein TODO dran (fehlende realloc-Fehlerbehandlung), das andere steckte in einer quick-and dirty-Testroutine (pointer am Programmende nicht deleted, aber der Compiler räumt nach Beedigung des Programms eh auf ;) Ich bin allerdings so ehrlich, zuzugeben, daß das das Ergebnis nicht an meinen überragenden ;) Programmierkenntnissen liegen kann. Oliver
Walter Tarpan schrieb: > Den Logik-Fehler oben hat mir aber keiner gemeldet. Der GCC 4.4 hätte dir für die beiden Anweisungen nach der fehlerhaften If-Bedingung ein "will never be executed" geliefert. Mit der Version 4.5 wurde dies Warnmeldung leider zu Grabe getragen. Der Compiler optimiert die entsprechenden Codezeilen zwar nach wie vor weg, informiert dich aber nicht darüber. Siehe auch: http://gcc.gnu.org/ml/gcc-help/2011-05/msg00360.html
:
Bearbeitet durch Moderator
Hallo Yalu, danke für diese Information! Viele Grüße W.T.
Oliver S. schrieb: > Das eine hatte schon ein TODO dran (fehlende realloc-Fehlerbehandlung), Tja, und ein paar Zeilen weiter hatte ich dann noch ein realloc, ohne TODO. Vermutlich deshalb hat cppcheck das nicht gefunden ;) Walter Tarpan schrieb: > scheint ja nicht so dolle zu sein Scheint so... Oliver
Naja, einestatische Analyse findet nicht alles. Für kostenlos kann man es aber im build mitlaufen lassen. Dafür hat EA einen Vorteil, es ist quasi false positive frei.
us73 schrieb: > http://clang-analyzer.llvm.org/ Nachdem ich so diverse Warnungen gesehen habe, die clang produziert, die für einen GCC nie ein Problem waren (obwohl völlig berechtigt), würde ich mal ein "+1" für clang hier setzen. Sollte man sich auf jeden Fall mal angucken, wenn man in dieser Richtung unterwegs ist.
Für Clang ist die Einstiegshürde wohl etwas höher; vor allem, wenn man in der Windows-Welt zuhause ist. Um selbstgeschriebene Makefiles scheint man auch zu brauchen. Also schiebe ich das mal auf eine mehr mittel- als kurzfristige Planung. Danke für den Tip!
Walter Tarpan schrieb: > Für Clang ist die Einstiegshürde wohl etwas höher; vor allem, wenn man > in der Windows-Welt zuhause ist. Da habe ich keine Ahnung. Ich aktualisiere mein System gerade auf eine FreeBSD-Version 10, da ist clang mittlerweile der Standardcompiler. ;) > Um selbstgeschriebene Makefiles scheint man auch zu brauchen. Wie das mit der Codeanalyse aussieht, habe ich mir noch nicht angesehen, aber ansonsten ist clang wohl verdammt aufrufkompatibel mit dem GCC.
Walter Tarpan schrieb: > Für Clang ist die Einstiegshürde wohl etwas höher; vor allem, wenn man > in der Windows-Welt zuhause ist. Ich hab gestern spasseshalber mal eine Windows-"Installation" angefangen. Nach einer halben Stunde svn sourcen laden was der damit immer noch nicht fertig. Compilieren dürfte da tagelang dauern, und dazu kommt noch das übliche Linux-Kleingedruckte (please install Python, Perl, gnutools, ....) Ich hab das dann abgebrochen. Das mag ja ein toller Compiler sein, aber so ist das wie die Harald-Schmidt-Show auf Sky: Unter völligem Ausschluß der Öffentlichkeit. Oliver
:
Bearbeitet durch User
Oliver S. schrieb: > Ich hab gestern spasseshalber mal eine Windows-"Installation" > angefangen. Nach einer halben Stunde svn sourcen laden was der damit > immer noch nicht fertig. Wenn du das eigentlich gar nicht haben willst, warum holst du dir denn dann unbedingt einen SVN-Snapshot? Für den braucht man auch beim GCC übrigens schnell mal eine halbe Stunde oder länger, selbst an einer guten Internetleitung. Wenn ich dort auf "Get Clang" gehe, dann bekommt man doch auch Releases und sogar fertige Windows-Binaries. Ich versteh' das Gejammer der "wir sind hier aber außen vor"-Fraktion nun gar nicht mehr. (Davon abgesehen: für Compiler-Entwickler waren und sind unixoide Systeme nun einmal schon immer die erste Wahl als Basis. Das hat mir letztens sogar jemand von IAR so bestätigt.)
Jörg Wunsch schrieb: > Wenn du das eigentlich gar nicht haben willst, warum holst du dir denn > dann unbedingt einen SVN-Snapshot? Ok, war mißverständlich, ich wollte den clang-analyzer, und der muß halt aus den clang-Quellen gebaut werden. clang selber gibt es als Windows-Installer. > Ich versteh' das Gejammer der "wir sind hier aber außen vor"-Fraktion > nun gar nicht mehr. Na ja, das klingt wie der Mathematiker im Käfig, der sich dadurch "befreit", daß er einfach "drinnen" in "draussen" umdefiniert ;) Oliver
Oliver S. schrieb: > Ok, war mißverständlich, ich wollte den clang-analyzer, und der muß halt > aus den clang-Quellen gebaut werden. Aber auch die muss man sich doch nicht zwingend aus dem SVN ziehen, sondern man kann auch einen Release-Tarball nehmen. Sollte deutlich einfacher und schneller sein. > Na ja, das klingt wie der Mathematiker im Käfig, der sich dadurch > "befreit", daß er einfach "drinnen" in "draussen" umdefiniert ;) Bliebe nur die Frage, wer von uns beiden der Mathematiker ist. ;-) Ich jedenfalls habe keine Probleme, die Software zu benutzen, die ich brauche ...
Jörg Wunsch schrieb: > Aber auch die muss man sich doch nicht zwingend aus dem SVN ziehen, > sondern man kann auch einen Release-Tarball nehmen. Sollte deutlich > einfacher und schneller sein. Kann durchaus sein. Da ich aber ausserhalb des Käfigs lebe, fehlt mir das enstprechende Insiderwissen, und habe ich mich schlicht an die Installationsanweisung von denen gehalten. Die fängt nun mal mit "load the sources from svn" an. Oliver
:
Bearbeitet durch User
Oliver S. schrieb: > Kann durchaus sein. Da ich aber ausserhalb des Käfigs lebe, fehlt mir > das enstprechende Insiderwissen, und habe ich mich schlicht an die > Installationsanweisung von denen gehalten. Die fängt nun mal mit "load > the sources from svn" an. Hmm, „Insiderwissen“ bezüglich llvm/clang habe ich auch keins. Aber verhindert der Aufenthalt im Windows-Käfig wirklich das Nachdenken? Da steht zwar am Anfang, dass man sich ein clang bauen soll, stimmt. Warum kann man von diesem Punkt aus aber nicht auf die Idee kommen, dass es ein vorgefertigter, vorhandener Build von clang das nicht auch tun könnte? (Zumal ja keinerlei Anweisungen gegeben werden, dass der Build für den Analyzer irgendwelche besonderen Zusatzoptionen bräuchte.) Weiter geht's ja in den Anweisungen mit:
1 | Once the Clang is built, you need to add the following to your path: |
Einzig die beiden Tools scan-build und scan-view muss man sich aus dem Sourcecode extrahieren (das steht aber auch so geschrieben, sie werden derzeit eben noch nicht automatisch ins Zielsystem installiert). Aber das bisschen clang-Sourcecode (10 MiB) ist relativ schnell geladen. Auch das wiederum kann man sich vom jeweils aktuellen Release laden. In der Tat funktioniert ein vorgefertigtes Binary problemlos, man muss es halt ggf. mit --use-analyzer dem scan-build-Script bekanntmachen (aber das sagt er einem auch, wenn er kein clang findet). Die größte Hürde für Windows dürfte eigentlich die Installation von Perl sein, denn scan-build und scan-view (die beiden Analyzer-Scripte) sind halt Perlscripte. Anbei ein Screenshot von scan-view für eine Datei, in die ich mal absichtlich zwei Fehler gebaut habe.
Jörg Wunsch schrieb: > > [...] > Aber verhindert der Aufenthalt im Windows-Käfig wirklich das Nachdenken? > Da steht zwar am Anfang, dass man sich ein clang bauen soll, stimmt. > Warum kann man von diesem Punkt aus aber nicht auf die Idee kommen, dass > es ein vorgefertigter, vorhandener Build von clang das nicht auch tun > könnte? > > [...] Ehrlich gesagt: Ich habe die Binaries auch nicht gesehen, bevor Du nicht erwähntest, daß es sie gibt. Wenn man gezielt sucht, sind sie zu finden. Sie sind übrigens hier: http://llvm.org/releases/download.html Vorher gingen meine Gedanken auch in Richtung: - "OK, Du brauchst Visual Studio 2012" - "hoffentlich beißt sich das nicht mit den beiden anderen Visual Studios (Visual Studio 2010 Prof. und Atmel Studio)" - "Vielleicht eine virtuelle Maschine für den Build aufsetzen? - "oder vielleicht eine virtuelle Maschine für Linux" - "Vielleicht mal wieder ein Cygwin oder KDE Win installieren - dann hast Du auch endlich wieder XFig (das einzige Linux-Programm, das ich in der Windows-Welt wirklich vermisse)" - "nee, cygwin geht laut Anleitung nicht" - "OK, verschieben wir das Ganze." Wenn sich jemand aus dem Projekt die Mühe macht, eine komplizierte Anleitung zu schreiben, gehe ich erst einmal davon aus, daß es momentan der einfachste Weg ist. Aber es ist schön, daß dem nicht so ist. So ließ sich clang total problemlos installieren und ist jetzt per Kommandozeile verfügbar. Also als nächstes schaun wir mal, wie sich der Analyzer hinzufügen läßt. Viele Grüße W.T.
Walter Tarpan schrieb: > Also als nächstes schaun wir mal, wie sich der Analyzer hinzufügen läßt. Den brauchst du eigentlich nur aufrufbar machen (also die beiden Perlscripte). Keine Ahnung, wie man das unter Windows macht, unter Unix läuft die Verknüpfung vom Script zum Interpreter ja über die #!-Zeile ganz oben. (Eventuell musst du sie unter Windows in .pl umbenennen, denn mit einer ordentlichen Endung bekommt Windows wieder die Zuordnung auf die Reihe.) Der erste Script ist so konzipiert, dass man ihn dem normalen Aufruf seines Builds voranstellt. Wenn man also sonst "make" sagt, dann sagt man für den Analyzer "scan-build make". (Bei der make-basierten Variante ist es wohl wichtig, dass das Makefile nicht die Variable CC überschreibt, denn die wollen sie mit dem für die analyse zu benutzenden Compiler überschreiben können.) Der zweite wertet dann nur die vom ersten hinterlassenen Daten über den Browser aus.
Ich kriege dieses Perl-Script unter Windows einfach nicht ans Laufen. Gibt es eine empfehlenswerte Linux-Distribution für den kleinen Test so zwischendurch in einer virtuellen Maschine? Debian?
:
Bearbeitet durch User
Walter Tarpan schrieb: > Ich kriege dieses Perl-Script unter Windows einfach nicht ans Laufen. Was passiert denn genau damit? > Gibt es eine empfehlenswerte Linux-Distribution für den kleinen Test so > zwischendurch in einer virtuellen Maschine? Debian? Hängt von deinem Geschmack ab. Wenn du sowas wie Ubuntu oder Mint nimmst, dann hast du den besten Komfort in Richtung Desktop, aber der kostet natürlich Speicher und CPU-Zyklen. Je einfacher du dahingehend wirst, um so weniger Ressourcen brauchst du, aber um so schwerer wirst du dich als jemand, der sonst Windows macht, damit tun. Kann man abrüsten bis zu Systemen mit reiner Textconsole.
Jörg Wunsch schrieb: > Kann man > abrüsten bis zu Systemen mit reiner Textconsole. Naja, bis auf Cppcheck sind ja alle Codeanalysetools, die ich testen kann, eh kommandozeilenbasiert. Also brauche ich ja nur Clang, Apt und Make. Windows-Nutzer zu sein hat ja nichts damit zu tun, die Kommandozeile zu schätzen zu wissen. Momentan lade ich Debian herunter. Ich halte es für sinnlos, soetwas auf meinem Raspherry machen zu wollen.
:
Bearbeitet durch User
Um die Tools an einzelnen Dateien zu testen, brauchst du die Perl-Skripte nicht unbedingt. Sie dienen hauptsächlich dazu, die Analyse automatisch innerhalb eines Build-Prozesses eines größeren Projekts mit den richtigen Präprozesor-Defines auf alle beteiligten Quellcodedateien anzuwenden. Letztendlich ruft das Skript auch nur clang auf. Da ich gerade nicht vor einem richtigen PC sitze, kann ich dir den genauen Aufruf nicht sagen. Soweit ich mich aber erinnere, ruft das Perl-Skript so etwas wie
1 | clang -analyze <viele weitere Optionen> <Dateiname> |
auf.
Yalu X. schrieb: > Um die Tools an einzelnen Dateien zu testen, brauchst du die > Perl-Skripte nicht unbedingt. Sie dienen hauptsächlich dazu, die Analyse > automatisch innerhalb eines Build-Prozesses eines größeren Projekts mit > den richtigen Präprozesor-Defines auf alle beteiligten Quellcodedateien > anzuwenden. > > Letztendlich ruft das Skript auch nur clang auf. > > Da ich gerade nicht vor einem richtigen PC sitze, kann ich dir den > genauen Aufruf nicht sagen. Soweit ich mich aber erinnere, ruft das > Perl-Skript so etwas wie > clang -analyze <viele weitere Optionen> <Dateiname> > > auf. Hallo Yalu, danke für den Tipp! Ja, einzelne Dateien lassen sich so schön überprüfen. Und bei meinem einfachen Testfall von oben (siehe Beitrag "Re: Statische Codeanalyse für den Hobbyprogrammierer" ), wo der cppcheck so versagt hat, kriege ich sinnvolle Meldungen.
1 | E:\>clang -analyze test.c |
2 | test.c:7:3: error: use of undeclared identifier 'a' |
3 | a=b; |
4 | ^
|
5 | test.c:7:5: error: use of undeclared identifier 'b' |
6 | a=b; |
7 | ^
|
8 | test.c:12:10: warning: incompatible pointer types returning |
9 | 'unsigned char (*)[6]' from a function with result type 'uint8_t *' |
10 | (aka 'unsigned char *') [-Wincompatible-pointer-types] |
11 | return &w; |
12 | ^~
|
13 | 1 warning and 2 errors generated. |
Jetzt habe ich den Debian allerdings so weit am Laufen... da ist die "Hürde" nur noch, das vom AVR-Studio erzeugte Makefile auf relative Pfade umzuschreiben. Und die Windows-Variante reicht für den kleinen Test zwischendurch. Eigentlich besser, als ich es mir erhofft habe. Ich hätte nicht gedacht, diese Wochenende doch schon sinnvolle Ergebnisse zu haben. Jetzt geht es mal fleißig ans Testen.
:
Bearbeitet durch User
@ Jörg Wunsch: Habe ich einen Denkfehler, bin ich blind, oder ist es wirklich so, dass der analyzer die Nullpointer-Dereferenzierung nicht anmeckert?
Haro schrieb: > Habe ich einen Denkfehler, bin ich blind, oder ist es wirklich so, dass > der analyzer die Nullpointer-Dereferenzierung nicht anmeckert? Musste es jetzt selbst erstmal probieren, aber zumindest für den einfachen Testfall meckert er das sehr wohl an.
Jörg Wunsch schrieb: > Haro schrieb: > >> Habe ich einen Denkfehler, bin ich blind, oder ist es wirklich so, dass >> der analyzer die Nullpointer-Dereferenzierung nicht anmeckert? > > Musste es jetzt selbst erstmal probieren, aber zumindest für den > einfachen Testfall meckert er das sehr wohl an. Ich bezog mich dabei auf deinen ersten Test: Beitrag "Re: Statische Codeanalyse für den Hobbyprogrammierer" Dort wird ja der Zeiger x, der mit NULL initialisiert wird, dereferenziert.
Haro schrieb: > Ich bezog mich dabei auf deinen ersten Test: Da wurde auch noch ein zweiter Fehler angezeigt, habe aber vergessen, was das war. Bei der Ansicht war ich dann nur in die Details gegangen, sodass man nur noch eine der beiden Beschwerden sieht.
Ah, ok. Alles andere hätt mich stark gewundert.
Hallo zusammen, gerade mal ein Jahr und eine Woche später bin ich so weit, das Ganze mal ernsthaft ausprobiert zu haben. Die Zwischenzeit hat (neben einer langen Projektpause) vor allem der Prozeß gebraucht, einen Mikrocontroller-Code auf den PC zu bringen - mit allen Stubs, einem neuen Build-Prozeß und dem ganzen Kram, der dazu notwendig ist. Hat sich das Ganze gelohnt? Jein. Teil der ganzen Aktion war es, daß sich jetzt der Quelltext auch mit dem Clang unter Linux bauen läßt. Der ist mit seinen detaillierten Fehlermeldungen eine große Hilfe und kann einige Tipps geben, die der GCC selbst -pedantisch für sich behält. Natürlich ist auch der Prozeß, ein µC-Programm auf den PC zu bringen sehr lehrreich - hatte ich bislang noch nie für den PC programmiert - und ich lerne noch täglich dazu. Die statische Codeanalyse selbst ist allerdings etwas enttäuschend. Bei so einer Funktion hatte er überhaupt nicht anzumeckern (Fehler mit Absicht eingebaut):
1 | uint8_t limadd_uint8(uint8_t a, int8_t) |
2 | {
|
3 | int8_t temp = a + b; |
4 | if (temp > (int16_t) UINT8_MAX) { |
5 | temp = UINT8_MAX; |
6 | }
|
7 | else if (temp < 0) { |
8 | temp = 0; |
9 | }
|
10 | |
11 | return temp; |
12 | }
|
Hier hatten weder die Codeanalyse noch Clang (3.5) etwas auszusetzen. Andererseits sind die false positives für mich regelrecht unverständlich (siehe z.B. angehängter Screenshot): Hier wird das Werkzeug durch das assert-Makro mit der Nase darauf gestoßen, daß "readbuffer" kein Nullzeiger sein kann - und nimmt trotzdem genau das Gegenteil an. Sehr überzeugend ist allerdings die Nutzung dieses Werkzeugs. Für ein auf der entsprechenden Plattform /build/-bares Programm das make-Skript einfach über ein anderes Programm aufzurufen und sich dann die Meldungen bequem im Browser anszusehen ist meiner Meinung nach ein sehr bequemes Bedienkonzept, ohne daß dafür eine spezielle IDE notwendig wäre. Hier ein klarer Pluspunkt. Mein Fazit bislang: Das Werkzeug ist deswegen gut, weil es - für PC-Programme - kaum Mehraufwand bedingt. Der Nutzen ist allerdings begrenzt - und zwar noch mehr, als ich im Vornherein erwartet habe. Viele Grüße W.T.
:
Bearbeitet durch User
> Hier wird das Werkzeug durch das assert-Makro mit der Nase darauf > gestoßen, daß "readbuffer" kein Nullzeiger sein kann ∗hüstel∗ noch einer der assert() nicht verstanden hat und die Doku dazu nicht gelesen hat.
Walter Tarpan schrieb: > uint8_t limadd_uint8(uint8_t a, int8_t) > { > int8_t temp = a + b; > if (temp > (int16_t) UINT8_MAX) { > temp = UINT8_MAX; > } > else if (temp < 0) { > temp = 0; > } > > return temp; > } Wenn das so ungestreift durch den Compiler geht, hast Du wohl noch irgendwo ein (globales oder statisches) b rumliegen.
Markus F. schrieb: > Walter Tarpan schrieb: > > [...] > > Wenn das so ungestreift durch den Compiler geht, hast Du wohl noch > irgendwo ein (globales oder statisches) b rumliegen. Nein, da kam noch ein Tippfehler dazu. Sollte heißen:
1 | uint8_t limadd_uint8(uint8_t a, int8_t b) |
2 | {
|
3 | int8_t temp = a + b; |
4 | if (temp > (int16_t) UINT8_MAX) { |
5 | temp = UINT8_MAX; |
6 | }
|
7 | else if (temp < 0) { |
8 | temp = 0; |
9 | }
|
10 | |
11 | return temp; |
12 | }
|
g457 schrieb: > ∗hüstel∗ noch einer der assert() nicht verstanden hat und die Doku dazu > nicht gelesen hat. Kannst Du das etwas genauer erläutern? Nach dem, was ich gelesen habe, sollte eine unerfüllte Assertion dazu führen, daß der Prozeß anhält und Feuer fängt und damit alles was danach kommt sicher sein können, nie ausgeführt zu werden.
> Kannst Du das etwas genauer erläutern? [..] alles was danach kommt sicher > sein können, nie ausgeführt zu werden. assert() ist sehr praktisch solange man am debuggen ist weil dann $debugger das Programm anhält, die IDE an $codestellste springt und man den aufgetretenen Fehler in vivo präsentiert bekommt. Aber es ist nicht dafür vorgesehen, im finalen Code zu verbleiben, macht ja auch keinen Sinn. Die üblichen(tm) Umgebungen setzen das dafür nötige NDEBUG im "release-Modus" per default, was bewirkt, dass das assert()-Statement dort zur Compilezeit(!) komplett wegfällt. Der langen Rede kurzer Sinn: Man darf sich ∗nicht∗ darauf verlassen, dass es beim assert() tatsächlich nicht weitergeht, sofern man nicht extra dafür vorgesorgt hat. Wenn man es trotzdem tut schreibt man extrem fehleranfälligen Code.
g457 schrieb: > er langen Rede kurzer Sinn: Man darf sich ∗nicht∗ darauf verlassen, > dass es beim assert() tatsächlich nicht weitergeht, sofern man nicht > extra dafür vorgesorgt hat. Ich glaube darin sind sich alle Nutzer einig. Das assert stellt lediglich sicher, daß bei allen Programm-Tests eine Bedingung immer erfüllt war - ansonsten hätten sich Annahmen, die dem assert zugrundelagen, als unzutreffend herausgestellt und die Codestelle hätte geändert werden gemußt. Was für mich im Umkehrschluß heißt: Das assert ist noch drin, also hat die Bedingung bislang immer zugetroffen (denn hätte sie einmal nicht zugetroffen, hätte der Code eh geändert werden müssen). Also kann der Code danach erst einmal davon ausgehen, daß die Bedingung immer erfüllt ist. Naja, vielleicht sieht der Code-Analyzer das anders - dann würde mich aber interessieren, wie.
> Also kann der Code danach erst einmal davon ausgehen, daß die Bedingung > immer erfüllt ist. Nein, nur für die Fälle, die Du tatsächlich abgetestet hast. Und ich kann mir nicht vorstellen, dass Du in obigem Beispiel mit malloc() ∗alle∗ möglichen Kombinationen von Speicherbelegungen abgetestet hast. Assert() nur solange der Debugger dranhängt, ansonsten richtig(tm) machen.
Vielleicht ist der false positive etwas ungünstig gewählt, weil er durchaus auch als korrekter Treffer gewertet werden kann. Aber wie kann ein Codeanalysewerkzeug den undefinierten möglichen Überlauf bei der Addition aufgrund des falschen Datentyps übersehen?
Integer Promotion!
> int8_t temp = a + b;
Wird temp wird auf int erweitert und damit macht der Code dann das, was
er (eigentlich) machen sollte.
Je nach Analyse Werkzeug bekommst du aber auch entsprechende Warnungen
angezeigt.
Christian schrieb: > Integer Promotion! Hmja. Mit ein Grund, warum ich froh bin, kein Softwareentwickler geworden zu sein.
Walter Tarpan schrieb: > Aber wie kann ein Codeanalysewerkzeug den undefinierten möglichen > Überlauf bei der Addition aufgrund des falschen Datentyps übersehen? Da kann nichts undefiniert überlaufen. a liegt von 0 bis 255, b liegt von -128 bis 127. Durch die integer promotion ist sowohl das minimale Ergebnis -128 als auch das maximale von 382 als "int" darstellbar, es ist also erstmal nichts undefiniert daran (allerdings durch die truncation u. U. nicht das, was du erwartet hättest). Allerdings bekomme ich beim clang dafür schon eine Warnung, wenngleich in der nächsten Zeile:
1 | foo.c:6:15: warning: comparison of constant 255 with expression of type 'int8_t' (aka 'signed char') is always false |
2 | [-Wtautological-constant-out-of-range-compare] |
3 | if (temp > (int16_t) UINT8_MAX) { |
4 | ~~~~ ^ ~~~~~~~~~~~~~~~~~~~ |
5 | 1 warning generated. |
Hallo Jörg, danke für die Erläuterungen. Jetzt verstehe ich auch den Hintergrund, warum ich nicht gewarnt werde: Durch die Integer Promotion ist fast jede Zuweisung an einen kleinen Integer-Typen eine Trunkierung, und bei -Wconversion bekomme ich damit für so ziemlich für jede Zeile mit einer (u)int(8/16)_t -Zuweisung eine Warnung. *) Ich bin mal gespannt, wann ich mich an die C-Integer-Regeln gewöhne. Edit: *) Ich sehe gerade, daß -Wconversion eigentlich für einen ganz anderen Zweck gedacht ist
:
Bearbeitet durch User
Walter Tarpan schrieb: > Polyspace scheint im oberen Preissegment angesiedelt zu sein. Ja das ist es. Wir hattens in der Firma, die Kosten lagen im fünfstelligen Bereich (exakte Lizenz und Zahl kenn ich nicht). Allerdings natürlich eine sehr mächtige Software, wir habens verwendet um Software für Raumfahrt zu analysieren. Walter Tarpan schrieb: > Ich bin mal gespannt, wann ich mich an die C-Integer-Regeln gewöhne. Ich empfehle dir, auch mal MISRA-C anzusehen. Dort gibt es sehr gute Beispiele wie man es macht oder auch eben NICHT macht. Da kommen genau solche Punkte drin vor.
ein_ingenieur schrieb: > Ich empfehle dir, auch mal MISRA-C anzusehen. Dort gibt es sehr gute > Beispiele wie man es macht oder auch eben NICHT macht. Da kommen genau > solche Punkte drin vor. Wobei MISRA meiner bescheidenen Meinung nach auch nicht das Gelbe vom Ei ist. Sicher macht es die Software "sicherer", aber nicht unbedingt auch immer leserlicher, vor allem wenn es um Pointer vs. Arrays geht :-/ Und dann gibt es noch die zahlreiche Codeschnipsel wo man sich entscheiden muss, ob der Compiler oder der MISRA Checker meckern darf, aber keine Lösung existiert womit beide zufrieden sind. Hat jemand mal Flexelint (die "gratis" Version von PC-Lint) probiert? (http://www.gimpel.com/html/flex.htm)
Eric B. schrieb: > (die "gratis" Version von PC-Lint A one user, non-floating license for one computer workstation is $998 Ich finde da nichts von kostenlos.
900ss D. schrieb: > Eric B. schrieb: >> (die "gratis" Version von PC-Lint > > A one user, non-floating license for one computer workstation is $998 > > Ich finde da nichts von kostenlos. Oh, hast du Recht. :-/ Ich hatte in Errinnerung, dass Flexelint die Evaluierungsversion war von PC-Lint und habe nicht weitergelesen. Gimpel bietet offensichtlich keine Evaluierungsversionen an...
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.