GOTO ist einfach cool: if (error) goto exit_error; Viel lesbarer als der ganze Kram wie if (0 != error) { error_bullshit = true; } if (error_bullshit != true) { do_secure_stuff(); } Bää..
Seh ich auch so. Richtig verwendet kann goto die Codekomplexität drastisch reduzieren und die Lesbarkeit des Codes massiv erhöhen. Viele der selbsternannten Codstylegurus sind jedoch zu borniert, um das zu kapieren.
Wer denkt sich bloß so einen Bödsinn aus? ? (mehr als 1000 Beiträge seit 26.09.01) "Rule 57 (required) The continue statement shall not be used." Da wird´s doch lächerlich... Was hat das bitte mit - embedded - Sicherheit oder - automotive zu tun? Antwort: Nichts... Da geht´s wohl eher um Gesinnung... Aber sobald irgendwer sowas als Standard bezeichnet und Automotive draufschreibt kommt garantiert irgendein Entscheider bei VW oder einem der Zulieferer zu der Erkenntnis: Dass muss ja was dran sein... selber denken ist dann nicht mehr nötig.
Re: Wer denkt sich bloß so einen Bödsinn aus? omniscient (mehr als 1000 Beiträge seit 26.09.01) Christian Stieber schrieb am 30. April 2013 15:04 > omniscient schrieb am 30. April 2013 14:52 > > > "Rule 57 (required) > > The continue statement shall not be used." > > > > Da wird´s doch lächerlich... > > Was hat das bitte mit > > - embedded > > - Sicherheit oder > > - automotive > > zu tun? > > Direkt erstmal nichts, Schön. > aber darum geht es auch garnicht. Doch darum geht´s. Denn die MISRA Regeln sollen genau diesem zweck dienen. Tun sie das aber nicht, wie du zutreffend bemerkst, sind sie unsinnig. > Man hat halt > einen Richtlinienkatalog; den hätte auch der Verband der > Waschmaschinenhersteller rausbringen können. Eben es sind Gesinnungsregeln. > Mit Sicherheit hat es wie meistens durchaus zu tun: 'continue' > (ebenso wie das Gegenstück 'break') sorgt dafür daß eine > Schleife auf > "unerwartete" Weise abgebrochen wird. Ein break ist ebensowenig wie ein continue "unerwartet". Die kommen nämlich nicht erst zur Laufzeit in den code sondern sind vom Programmierer an den dafür wohlbestimmten Plätzen regelmäßig nach eintritt von vorbestimmten Nedingungen. > Das kann insbesondere bei > komplexeren Schleifen leicht > die Unlesbarkeit fördern Eine komplexe schleife ist bereits komblex. Ein break oder continue mach es nicht unlesbarer sondern deren Vermeidung führt zu gestelzten Konstrukten, die gerade die Lesbarkeit verschlechtern. > und somit > leichter fehlerhaften Code nach sich ziehen. Das ist Quatsch mit Soße... Da ist keinerlei Kausalzusammenhang.
Re: Doch Blödsinn ylai (mehr als 1000 Beiträge seit 11.05.01) EinmalMitProfisArbeiten schrieb am 1. Mai 2013 01:10 > target[j++] = src[i]; Ich bin recht sicher, dass das nicht "legal" nach MISRA ist. Die Inkrementierung muss eine separate statement haben. > Aber nehmen wir einmal an, das continue wäre an dieser Stelle > wirklich realistisch und sinnvoll. Dann führen Regeln wie die in > MISRA-C nur dazu, dass Programmierer sich irgendeinen Workaround > ausdenken. MISRA ist nur teilweise sinnvoll (wie die 1:1 aus Scott Meyers Bücher übernommene Regeln). Der Rest ist aber pervers, in dem sie sichtlich C/C++ zu etwas zwischen BASIC und Ada kastrieren will.
Es gibt keine "intrinsische Sicherheit". ? (mehr als 1000 Beiträge seit 31.08.11) Auch mit dem besten Ruleset nicht. Den Therac-25-Fehler könnte man problemlos MISRA-kompatibel gestalten.
Re: Wunschdenken: intrinsisch sicheres C(++) Trollplonk (mehr als 1000 Beiträge seit 02.06.03) NeoBoot schrieb am 30. April 2013 14:54 > Ich bin mir verdammt sicher, dass es ein Traum bleiben wird. Aber > angenommen, die MISRA-Regeln würden in den C und C++ Standard > aufgenommen. Angenommen, der Compiler würde einem, anstatt potentiell > unsicheren Mist zu kompilieren, lauter Fehler um die Ohren werfen, > bis der Code endlich garantiert sicher ist. Die Welt wäre ein > schönerer Ort. 1. Du willst also praktisch eine neue Programmiersprache entwerfen, in der man keine Denkfehler mehr machen kann. 2. Das ist unmöglich. 3. Am Beispiel PHP sieht man, daß die User so eine Programmiersprache auch gar nicht wollen. > Eher erwarte ich aber, dass die µC-Hersteller Rust adoptieren, als > sowas. Wobei, MISRA unterstützt z.B. die IAR-Toolchain nativ. Leider Die "Entwicklungswerkzeuge" von IAR Systems zählen mit zum Schlechtesten, was ich während meiner ganzen Berufstätigkeit benutzen mußte. > als schwer kostenpflichtige Zusatzoption. Und Sicherheit als > Bezahloption ist uncool. Stimmt, IAR war zwar scheiße, aber wenigstens teuer und mit Dongle! Trollplonk Mein Name ist Programm.
? (3 Beiträge seit 01.05.13) ? schrieb am 30. April 2013 16:59 > Das continue-Statement > ist eine sehr beliebten Fehlerquelle. Wenn man das continue-Statement verbietet, führt das nur zu sinnlosen Workarounds. Statt while (X) { if (Y) continue; Z; } wird dann eben folgendes geschrieben: while (X) { if (!(Y)) { Z; } } So etwas bringt niemanden weiter. continue-Statements sind ein Symptom eines komplexen Kontrollflusses, und nicht dessen Ursache. Entsprechend sinnlos ist es, sich von ihrem Verbot eine Verringerung der Komplexität (und damit der Anzahl der Bugs) zu erhoffen.
Re: Das ist nur die konsequente Umsetzung einer Philosophie. Arkarit (689 Beiträge seit 02.05.09) EinmalMitProfisArbeiten schrieb am 1. Mai 2013 02:06 > Garban schrieb am 30. April 2013 16:59 > > > Das continue-Statement > > ist eine sehr beliebten Fehlerquelle. > Wenn man das continue-Statement verbietet, führt das nur zu sinnlosen > Workarounds. Statt > while (X) { > if (Y) > continue; > Z; > } > wird dann eben folgendes geschrieben: > while (X) { > if (!(Y)) { > Z; > } > } > So etwas bringt niemanden weiter. continue-Statements sind ein > Symptom eines komplexen Kontrollflusses, und nicht dessen Ursache. > Entsprechend sinnlos ist es, sich von ihrem Verbot eine Verringerung > der Komplexität (und damit der Anzahl der Bugs) zu erhoffen. Genau das ist der Punkt, mit dem unsere "Philosophen" augenscheinlich hoffnungslos überfordert sind. Ein lokales "goto" und natürlich erst recht ein "continue" können im richtigen Kontext absolut die Lösung der Wahl sein. (Ersteres zugegeben sehr selten). Treten damit Probleme in der Übersichtlichkeit auf, liegt das im Allgemeinen a) am Kontext selbst, nämlich zu langen Funktionen, zu hohe Schachtelungstiefe etc. oder b) an der Unfähigkeit des Programmierers. Wer mit einem "continue" allerdings nicht klarkommt, wird bei angeordnetem Verzicht darauf trotzdem scheitern und sich - wie Du richtig schreibst - einen regelkonformen, aber mindestens ebenso fehlerhaften Workaround zurechtfrickeln. Und auch im Fall "MISRA" ist es nicht die Sprache, sondern der Kontext, der Probleme macht. Nicht falsch verstehen, ich liebe C und C++, aber wenn es um höchste Sicherheitsansprüche geht, kann es eigentlich nur einen Programmierstandard für diese Sprachen mit einem einzigen Paragraphen geben: §1: Nehmt was anderes.
? ? (27 Beiträge seit 26.07.12) Dieser Schwachsinn erinnert mich an einen früheren Berufsschullehrer. "Verwenden sie kein break! Break ist für Hacker, aber nicht für Programmierer." Vor Fremdschämen wurde es mir beinahe schwarz vor Augen...
? (mehr als 1000 Beiträge seit 16.06.00) ? schrieb am 1. Mai 2013 01:10 > ? schrieb am 30. April 2013 17:28 > > > Kurzes Beispiel: > > > > for(i=0, j=0; src[i];) > > { > > if(src[i]<'A' || src[i]>'Z') > > continue; > > > > target[j]=src[i]; > > i++; > > j++; > > } > Das Beispiel überzeugt gleich aus mehreren Gründen nicht. Zum einen > würde jeder normale Programmierer i im Schleifenkopf inkrementieren > und nicht im Rumpf: > for (i = 0, j = 0; src[i]; ++i) > { > if (src[i] < 'A' || src[i] > 'Z') > continue; > target[j++] = src[i]; > } > (Ich gehe mal aus, dass der Sinn dieses Codes sein sollte, den String > zu kopieren und alle Zeichen außer A-Z zu entfernen). Und auch das > ist nicht realistisch, denn wieso sollte man an dieser Stelle > überhaupt ein continue verwenden? So ist es viel einfacher: > for (i = 0, j = 0; src[i]; ++i) > if (src[i] >= 'A' && src[i] <= 'Z') > target[j++] = src[i]; > > Aber nehmen wir einmal an, das continue wäre an dieser Stelle > wirklich realistisch und sinnvoll. Dann führen Regeln wie die in > MISRA-C nur dazu, dass Programmierer sich irgendeinen Workaround > ausdenken. Man würde dann zum Beispiel schreiben > for(i=0, j=0; src[i];) > { > if(!(src[i]<'A' || src[i]>'Z')) > { > target[j]=src[i]; > i++; > j++; > } > } > , und das weist genau den gleichen Fehler auf. Ein Verbot des > Continue-Statements bringt gar nichts, weil die gleichen Fehler > einfach auf andere Weise gemacht werden. Ich bin schockiert, eine korrekte, sachliche und bemühte Antwort. In den Developer-Foren verspüre ich häufiger das dringende Bedürfnis, alles in 5 Sekunden abzufackeln und ein Killerkaninchen zur Bewachung der verbrannten Erde abzustellen... hmm, nein zwei Killerkaninchen (dann gibt es hoffentlich Nachwuchs ;) - weshalb ich dann oft nicht reingehe und auch nichts schreibe. Zum Thema: ich würde Regelfanatiker immer nur zu gerne nochmal durch einige Vorlesungen aus der Theoretischen Informatik scheuchen, nur damit endlich mal der Groschen fällt. Mit diesen Regeln wird keine neue Programmiersprache geschaffen, sie können auch die charakteristischen Fehler gar nicht verhindern, dafür sind sie aus mathematischer Sicht zu wenig modifizierend. Ich kann also denselben Müll auch in MISRA völlig problemlos abliefern. Und ich hatte in letzter Zeit einiges aus der Automobilbranche auf dem Tisch und muss sagen, dass das auch gemacht wird. Die Leute sind sehr kreativ, sie überschreiben auch nach wie vor mühelos rückwärts die lokalen Variablen auf dem Stack, referenzieren mit großer Freude Null-Pointer an selten betretenen Programmpfaden und verlieren sich in Endlosschleifen. Und solche Fragmente werden nur zu gerne von "Copy & Paste"-Entwicklern dann weiter verbreitet, weil es ja "bisher" auch nicht geknallt hat. Davor kann MISRA nicht schützen. Und natürlich auch nicht vor den besonders schönen Problemen mit Threads und parallelen Programmabläufen. Wenn man sagt, man hätte gerne eine Art "sinnvolles" Style-Guide, bei dem manche Regeln höher gewichtet werden und andere nur Empfehlungen sind, das kann ich nachvollziehen. Aber irgendeinen völlig unwissenschaftlichen Blödsinn über solches Zeug zu behaupten, halte ich auch in Anbetracht der Business- und Bullshitbingo-Apologeten, die sich in der Softwareentwicklung breitmachen, für eine ganz, ganz schlechte Idee und fachlich schlichtweg für Irreführung. MFG/?
Wem Softwareentwicklung selber zu schwierig ist ... ? (mehr als 1000 Beiträge seit 02.06.03) ... der kann wenigstens noch andere schikanieren, indem er für sie total sinnvolle Codier-Richtlinien erfindet, wo alles, was er selber nicht kapiert hat, unverständlich, gefährlich, unsicher und verboten ist. ? Mein Name ist Programm.
Vermutlich ja. ;-) Bei einigen Regeln habe ich leider auch den Eindruck, das man C auf Kindergartenniveau downsizen will. Etwa wenn man bedingte Zuweisungen generell verbietet. Gut, verschachtelt werden die etwas kryptisch, aber sie helfen den Source-Code kompakt und lesbarer zu halten.
Re: Wem Softwareentwicklung selber zu schwierig ist ... ? (mehr als 1000 Beiträge seit 02.06.03) ? schrieb am 1. Mai 2013 12:26 > "Standards" wie MISRA kann man diese leider nur atomar betrachten. In > kaum einem Unternehmen wird gesagt, lass uns mal ein bischen MISRA > machen und nur das sinnvolle. Meist wird es heißen, absofort MISRA > und dann wird mit einem Tool die Einhaltung überprüft. Dabei kommt > der schlechteste MISRA konforme Code durch, aber sauberer nicht MISRA > konformer Code muss kaputt gefixt werden. Wenigstens Du hast das Grundprinzip von Codierrichtlinien verstanden. Genau so läuft es nämlich bei jedem Großprojekt! ? Mein Name ist Programm.
Reizthema Klammern wa (mehr als 1000 Beiträge seit 13.01.00) Christian Stieber schrieb am 30. April 2013 14:31 > Natürlich gibt es eine klare Reihenfolge was "a && b || c" bedeutet Nun, ueber sowas meckert bereits der Compiler gern mal. Ist auch in aller Regel allein schon wegen der Laenge solcher Ausdruecke schwer lesbar. Ein paar hilfreiche Klammern, idealerweise gepaart mit durchdachten Zeilenumbruechen, sind hier also nuetzlich. > Auch bei Konstrukten wie "*p++" ist nicht sofort ersichtlich was > passiert. "*(p++)" oder "(*p)++" machen das klar. Da verwirrt mehr als es nuetzt. *p++ ist derart "normal", dass man sich bei *(p++) erst mal wundert, was hier denn seltsames passiert, dass die Klammern noetig sind. Ist "p" vielleicht ein Macro ? Usw. Ein Uebermass an Klammern verschlechtert auch die Lesbarkeit des Codes. So wird keinem geholfen: der Compiler haette es auch ohne die Klammern verstanden, und der Programmierer muss sich darauf konzentrieren, Klammern zu entflechten, statt den Sinn des Codes zu erfassen. Beispielsweise sollte man auch das Pascals verpfuschten Prioritaeten zu verdankende Setzen von Klammern um relationale Ausdruecke vermeiden. Also "a == b || a == c" statt "(a == b) || (a == c)". In diesem einfachen Fall ist das zwar immernoch lesbar, aber man kommt so recht schnell zu kryptischen Klammerwuesten. - ?
Ist die Aufforderung ... ? (mehr als 1000 Beiträge seit 31.08.11) .. die Operatorpräzedenz von C nicht als verbindlich anzusehen, immer noch drin? Also nicht vergessen: c = a + b; geht so nicht, denn der Compiler könnte es auch als (c = a) + b; interpretieren, wenn er sich nicht an die Operatorpräzedenz hält. Also immer schön Klammern setzen, viele viele Klammern: c = (a + b);
Re: Wunschdenken: intrinsisch sicheres C(++) ? ?, ? ? (mehr als 1000 Beiträge seit 10.01.00) Compiler geben Dir bereits einen Haufen Warnungen, und man kann die auch in Fehler "umschalten". Wenn man denn möchte... Und genau daran hakelt es ja schon. Ich kämpfe regelmäßig mit z.B. Boost, weil diese Sammlung von zusammengefrickeltem C++ Code bei "scharfen" Einstellungen anfängt Warnings zu produzieren. Und bei mir sind "scharfe" Einstellungen ebenso wie "-Werror" bzw. "/WX" der Standard... In anderen Fällen produziert "Open Source" Software beim Übersetzen seitenweise Warnings, obwohl die Makefiles nichtmal "scharfe" Warnings einschalten. Aber solange es keine Errors sind hält es halt niemand für nötig sich darum zu kümmern. Ich habe jetzt auch wenig Grund zu vermuten daß es bei "closed Source" irgendwie besser aussieht. Da sieht man es halt nicht mehr. Und wenn ich z.B. Code von "unseren" Indern sehe... da werden ständig irgendwelche globalen Bools in obskurer Weise gesetzt und abgefragt, da wird quer in der Gegend rumgesprungen was das Zeug hält, da werden Implementierungen von Libraries angeschaut und das Zeug in gruselig undokumentierter Weise verwendet, da werden Millionen obskure Statusteilinformationen in der Gegend rumgeschoben, und bei irgendwelchen Kombationen macht die "Save" Funktion dann schonmal einen "Load" oder so. Oder Threads ohne Synchronisation. Oder oder oder... Entsprechend funktioniert das Zeug dann auch. Sicherheit, Qualität und Zuverlässigkeit fangen im Kopf an. Ob Du den Nagel gerade oder krumm reinschlägst hängt nur sehr gering vom verwendeten Hammer ab.
? (mehr als 1000 Beiträge seit 20.11.12) ?.M schrieb am 3. Mai 2013 22:28 > > Wolltest du gerade sagen, dass der Linux Kernel > > mit C++ sauberer wäre? > > Aber um Größenordnungen. Nein. Eindeutig nein. Ich weiß nicht, im welchen Bereich du tätig bist, aber wenn man selber in dem "low level" Bereich tätig ist, muss man C++ fürcherlich finden. Ich sage nicht, C++ ist allgemein fürchterlich, aber in dem low level Bereich ist es eindeutig grausam. Und das aus vielen Gründen, die ich hier nicht auflisten möchte. z.B. möchte ich keine virtuellen Methodentabellen auf Kernel-Ebene haben. Ich möchte/muss den Speicher vollständig überblicken können und kann mir keine unsichtbare Tabellen erlauben. Darüberhinaus brauche ich sie überhaupt nicht. Mach dich schlau, wie Klassen, Vererbung usw. im Speicher abgebildet werden. Das, was da generiert wird gehört niemals im Kernel. Ich würde dir empfehlen, dich schlau zu machen, wie der Punktoperator überhaupt funktioniert. Also was alles konkret passiert, wenn du objekt.function() aufrufst. Das, was da passiert gehört niemals in einem Kernel, im Treibercode und allen (echtzeit) Systemen, die völlig deterministisch arbeiten müssen. Es gibt Fälle, wo sogar Funktionen zu viel sind und man schreibt Makros stattdesen. Man kann sich da nicht mal einen Funcktionssprung erlauben. Da mit Klassen und Methodentabellen zu kommen ist Selbstmord und hört sich nach WINFler. Klassen in Interrupt Handler... Gott im Himmel, mir wird schlecht. Btw, es gab Experimente mit C++/Linux und die sind gescheitert. Die Wartbarkeit ist nicht gestiegen, sondern gesunken. > http://lwn.net/Articles/249460/ Wenn C++ toll in deinem Bereich ist, ok cool. Aber bitte nicht behaupten, C++ sei überall toll. > C++ bietet ne tolle Möglichkeiten große Projekte besser > zu strukturieren. Nein. Es sei denn, man hat wirklich keine Ahnung von C. Der Kernel ist wunderbar strukturiert und das ohne C++. > Richtiges OOP, OOP ist ein Modell von vielen. Warum müsste ich unbedingt OOP machen? Es geht wunderbar auch ohne. Ich selber war jahrelang mit Java unterwegs. Ich sehe es aber nicht ein, dass OOP ein Ziel in sich sein sollte. Und zum Thema "richtiges": ich kann durch Pointerarithmetik auf dein "private" Zeugs zugreiffen. Völlig mühelos. Und was heißt richtig überhaupt? Warum soll Python-OOP schlecht sein? > generische Programmierung, Ich brauche sie überhaupt nicht. Auch mit Java habe ich sie nur selten gebraucht. Und *wirklich* gebraucht habe ich sie nie. > RAII, Exceptions. Ich brauche sie nicht. Und im Treibercode möchte ich wirklich keine Exceptions sehen. Aus verschiedenen Gründen. > Nur haben Leute die Betriebssysteme eine Lowlevel-Denke > die sich nicht mit Abstraktion (die im Falle von C++ kaum > Performance kostet) nicht vereinbart. Hä? Ich sehe in dem Linux-Treibermodell viel mehr Abstraktion als in vielen C++/Java Projekten. Kann es sein, dass du einfach keine Erfahrung auf dem Gebiet hast und nur so allgemein von C++ ist cool redest? Sag einfach so, dass du nur C++ kennst und dass du es toll findest. Cool.
Ich bin mal den MISRA-C-Standard durch und habe fast für JEDE Regel eine Ausnahme gefunden. Ich sehe es genauso wie Du. Es ist ein guter Hinweis, solche Regeln zu kennen und vor allem die Motivation, die die Leute damit haben. Ich habe nur eine Regel: fass Dich kurz, aber nutze alle Möglichkeiten von C, damit Code sauber ist (möglichst strenge und exakte Typen, drastische Scope-Eingrenzungen etc.). Allerdings kann man diese Regel nur durchsetzen, wenn man genügend Erfahrung hat. Ich bin sogar dagegen goto zu verbieten. Ich habe genau EIN Beispiel für gute Praxis damit gefunden und dazu von renomierten C-Hackern und da darf man von denen lernen.
Das Problem mit MISRA habe ich insofern, als dass ich (laut Kundenfeedback) ein sehr guter Programmierer bin, der eben auch von sich aus leserlichen Code schreibt. Ich würde durch MISRA definitiv massiv ausgebremst und der Code würde unleserlicher mit, als nach meinen eigenen Regeln. MISRA ist die Anwort von Managern auf die Frage, wie programmier-unerfahrene Ingenieure fehlerarmen C-Code schreiben können. Das Dilemma: es geht nicht! Leider begreifen die Verantwortlichen das einfach nicht, oder nutzen den Microsoft-Effekt aus: wenn der PC muckt unter Windows, kann man die Schuld auf Microsoft abladen und man selbst ist fein raus; wenn man dagegen Linux nutzt, ist man selber Schuld, wenn es mal Probleme gibt. Genau _so_ "verkauft" sich MISRA. Letztlich können nur gute _embedded_ Programmierer guten Code schreiben. Die brauchen dann aber auch kein MISRA, sondern gescheite Style Guides. Damit kann man auch einige extrem nützliche Extensions moderner Compiler wie GCC erlauben, die gerade auch zur Qualtität des Codes massiv beitragen können (Stichworte "gcc plan9-extensions"). MISRA stammt immerhin aus einer Zeit, als die meisten embedded Compiler noch K&R-C implementierten und moderne Programmiertechniken (also der 70er Jahre!) den Auto-Ingenieuren völlig unbekannt waren. Das gilt leider auch für die Leute, die MISRA erst definiert hatten. Inwieweit das mit MISRA-2012 anders ist, kann man leider aufgrund der Paywall nicht so einfach feststellen.
Ich auch ned, wundere mich aber dauernd über die - trotz MISRA - häufingen Liegenbleiber und Rückrufe wegen Softwarefehlern in Steuergeräten. Und das ausgerechnet in den "Premium" Mühlen. Wie gesagt: erfahrene SW-Entwickler brauchen MISRA bestenfalls anfangs als Liste möglicher Pitfalls (dafür ist es tatsächlich ok, wenn auch (MISRA-2004) massiv unvollständig). Und schlechte Progger werden mit MISRA nicht wirklich guten Code schreiben.
Wie gesagt, ich bin extrem froh, nicht MISRA nutzen zu können. Das erlaubt mir eben die plan9-extensions nutzen zu können, also OOP in C ohne overhead, etc. und das typsicher (Compiletime) ohne die cast-Krankheit. Ebenso das union-Verbot von MISRA. Fakt ist, dass MISRA mit seinen Regeln schlicht die Möglichkeiten moderner Compiler verhindert (daher sind die commerziellen embedded-Compiler ja oftmals auch derartige Krücken) und moderne Programmiertechniken unterbindet. Obwohl beides masiv zur Qualität beitragen könnte. Dafür sieht man immer noch, dass z.B. Variablen zwischen Threads (bzw. interrupt handler und normalen code) nicht als volatile deklariert sind. Ja, das mag auch IAR&Co laufen, weil die Teile eben mit solchen Deppen rechnen, aber es behindert die Optimierung gescheiter Compiler. Das Allerwelts-Heilmittel der Manager Unit-/Integration-/etc.-Test wirds ja schon finden... Der beste Test ist der, den man nicht schreiben muss, weil der Testcase gar nicht auftreten kann.
Übrigens habe ich sowas oft auch so implementiert gesehen: int ok = 1; i = 10; while ( ok ) { ... i--; if ( i == o) ok = 0; } MISRA konform, aber völlig unübersichtlich.
>> Also auch kein Flag in der Schleifenbedingung, das man >> unterwegs auf 'fertig' setzt? > Warum? > done = FALSE; > for(ii = 10; ii > 0; --ii) { > if(done == FALSE) > { > ... > if(...) > { done = TRUE; } > } > } > So vermeidet man, die Schleife abbrechen zu müssen - man führt > alle Durchläufe durch, macht aber eventuell nichts. Dein "eventuell" deutet ja schon darauf hin: solcher Art Programmierung ist nur mehr dazu da, irgendwelche hahnebüchenen Standards zu erfüllen, rückt aber von klarer Logik bzw. Verständlichkeit weit ab. Denn, wenn das "done"-if irgendwelchen Nachbarcode bekommt, dann ist die Schleife doch nicht so ganz done, und wenn es keinen bekommt, dann verliert es seine Existenzberechtigung, denn einen Schleifenzähler leer raufzählen lassen ist verwirrend, weil es andeutet, dass dadurch eine Invariante erfüllt wird oder, ganz schlimm, im for() irgendwelche side effects ausgelöst werden. Safe code wird nicht durch das Ignorieren von POLS erreicht, sondern durch ein besseres Abstraktionsniveau. Also wenn schon, dann ganz weg mit der C for-Schleife und was klares, eingeschränktes verwenden für solche Programmteile, aber nicht irgendwelchen style Unfug, der nur durch Reviews halbwegs validierbar ist.
>> ...und noch dazu sehr dürftig. >> Der Artikel ist nur für Leute geschrieben, die MISRA sowieso schon kennen. >> Schade. > Oder für Manager, die C sowieso nicht kennen, mit > Beispielen also nichts anfangen könnten. Bingo. MISRA wird vor allem in diesen Etagen als Buzzword verwendet, das die Hoffnung befoerdert, "irgendwie" bessere Software hervorzubringen als ohne MISRA. Das ist der wahre Verdienst des Konsortiums: MISRA als selling point. Was dahinter steckt, kuemmert nicht. Ein klein wenig wie ein angebissener Apfel... :D
Eher wuerde ich sagen: ohne Rekursion und goto bekommt man eine Motorsteuerung hin, nicht aber ohne Pointer. Das Arbeiten mit physikalischen Systemen bedingt fast immer auch die Benutzung von verschiedensten (multidimensionalen) Tabellen, die ohne Filesystem in wunderlich segmentierten Flashbereichen liegen, und wer C halbwegs kennt, weiss, wie sehr dieses "kein Pointer"-Paradigma in so einem Fall zum Selbstbetrug, zur Verkomplizierung und moeglicherweise sogar zur Performance-Bremse wird.
> Kann man nachvolliehen. Nicht wirklich. a[i] syntaktischer Zucker für *(a + i). Man benutzt also in jedem nichttrivialen C-Programm Zeigerarithmetik, auch wenn man das vielleicht nicht auf den ersten Blick sieht. Und ich weiß auch nicht, wem dadurch geholfen werden soll, dass man &a[i] statt a+i schreiben muss. Naja, außer Leuten, die die o. g. Beziehung zwischen [] und *(+) nicht verstehen, aber die sollten sowieso nicht in die Nähe eines Compilers gelassen werden.
>> a[i] syntaktischer Zucker für *(a + i). >> [...] wem dadurch geholfen werden soll, dass man >> &a[i] statt a+i schreiben muss. > Und weil + kommutativ ist, kann man auch gleich i[a] schreiben. > Ich finde es sehr gut, wenn man sich da auf _eine_ sinnvolle Schreibweise festlegt. Die sinnvolle Schreibweise ist a + i und nicht &a[i]. Letzteres ist syntaktischer Zucker für &*(a+i), und das ist offensichtlich Unfug. Es kommt doch auch niemand auf die Idee, &*a statt a zu schreiben. >> Naja, außer Leuten, die die o. g. Beziehung zwischen [] und *(+) >> nicht verstehen, aber die sollten sowieso nicht in die Nähe >> eines Compilers gelassen werden. > Ist das noch Arroganz oder schon Überheblichkeit? Ist es auch arrogant, wenn man die Meinung vertritt, dass sich jemand, der Gas- und Bremspedal nicht auseinander halten kann, aus dem öffentlichen Straßeverkehr heraushält? -- Ich würde sagen weder noch. Wer seine Sprache nicht beherrscht, sollte tatsächlich nicht an kritische Projekte herangelassen werden - MISRA hin oder her.
MISRA wurde von der Automotive-Industrie in der Rueckschau entworfen, als klar wurde, dass mit der Sprache C nicht mal "eben so" programmiert werden konnte, weil selbst informatisch ausgebildete Nicht-C-Programmierer (und die am Beginn weit verbreiteten umgeschulten Elektrotechnik und Maschinenbau-Ingenieure sowieso) ueber die Unzulaenglichkeiten der Sprache stolpern. Polemisch gesagt, aus Nicht-C-Programmierern werden miserable C-Programmierer, daher der Name. Warum sich gerade die (deutsche) Automobilindustrie so bereitwillig in die Geiselhaft der Sprache C begeben hat, ist mir noch heute schleierhaft, denn die Tools (Compiler) fuer den Loewenanteil der Steuergeraete waren noch bis weit nach 2000 vollkommen hahnebuechen, teilweise sogar von C89 abweichend (erinnert sich noch jemand an den Cosmic-Praeprozessor?) und bei der Handvoll an automotive-grade CPUs haette die Finanzierung z.B. einer Modula-2 Toolchain im Nachhinein gigantische Kosten gespart. So stehen wir nun noch immer mit C da, C89 ist durch Autosar fuer weitere Jahre als Standard einzementiert, es gibt Heerscharen an Beinahe-Programmierern, die zwar MISRA befolgen, aber die zugrunde liegenden Probleme (wie C die abstrakte Maschine auf ihre reale Plattform abbildet) nicht annaehernd verstehen, und ein Haufen Manager, die sich mangels Fachkenntnis an leicht zu merkenden Begriffen wie MISRA und Autosar festhalten. Fazit: fuer jemanden der C beherrschen will, sollte die Religion "LINT" und nicht MISRA sein.
Der_Irre_Polterer (mehr als 1000 Beiträge seit 23.02.04) Diethilde schrieb am 20. September 2013 23:26 > if ((read_c0_prid() & 0xff) >= 0x0050) > return read_c0_count(); > break; > > Wenn ich sowas sehe kriege ich Wutanfälle. Ohne Grund > return mitten drin. Ist sogar guter Stil. "One return" war ein Irrweg aus den 60ern. Geboren aus Gedanken an Prozesoren ohne Pipelines und on-Chip-Caches > Literale statt Symbole. In diesem Fall tatsächlich übersichtlicher. > Funktionsaufruf als Operand. Yep. Guter Stil: Retun value optimization
Re: Denkt denn keiner an die Übersicht! Roland Weber, Roland Weber (mehr als 1000 Beiträge seit 05.07.02) bazzo schrieb am 21. September 2013 20:53 > Ein einziger Ausgang aus einer Funktion ist und bleibt einfach > übersichtlicher! Das kommt ganz darauf an, wieviel Code zwischen der Stelle, wo der Rückgabewert feststeht und der Stelle, wo das "return" steht, noch übersprungen werden muß. Ich persönlich frage meistens ganz am Anfang einer Methode ein paar Sonderfälle ab, die zum Beispiel zu einem null-Rückgabewert oder einem bestimmten Boolean-Ergebnis führen. Dann schreibe ich das return auch genau da vorne hin. Das finde ich sehr viel übersichtlicher, als praktisch den gesamten Methodenrumpf in ein if zu kapseln und weiter einzurücken, nur damit am Ende ein einziges return stehen kann. ciao, Roland
Re: Denkt denn keiner an die Übersicht! Diethilde (mehr als 1000 Beiträge seit 20.11.12) Völlig verständlich und auch gängig. Es ist natürlich übersichtlicher, wenn man schreibt if (data == NULL) return ERROR_DATA; if (buffer == NULL) return ERROR_BUFFER; read(data, buffer); als if (data != NULL) { if (buffer != NULL) { read(data, buffer); ... } else { return_val = ERROR_BUFFER; } } else { return_val = ERROR_DATA; } return return_val; Manchmal aber geht es um die Einhaltung von Coding Styles, die keine Abweichungen erlauben und die u.U. nerven.
Re: if ((read_c0_prid() & 0xff) >= 0x0050) Pickwick81 (mehr als 1000 Beiträge seit 12.07.02) Diethilde schrieb am 22. September 2013 00:14 > Nein. Grund ist: für komplizierte Dinge ist es hilfreich, davon > ausgehen zu können, dass es nur ein return gibt. Für komplizierte Dinge ist es hilfreich, genau das zu tun, was man zum jeweiligen Zeitpunkt weiß, weil das Codezeilen spart und Komplexität verringert. Wenn man weiß, dass man fertig ist, beendet man also. Ganz simpel eigentlich. > Nop, Return value optimization ist eine Compiler-optimierung, nicht > eine Sache die du machen solltest: Trotzdem kann man solche Dinge wissen und dem Compiler helfen und im konkreten Fall kann man sich eine extra Variable im umgebenden Gültigkeitsbereich nun mal sparen.
Re: if ((read_c0_prid() & 0xff) >= 0x0050) Amoebus (8 Beiträge seit 23.12.12) > return mitten drin. Das unbedingte "Return am Ende" liegt vernünftigerweise schon ziemlich lange auf dem Müllhaufen der Programmier(-Stil)-Geschichte.
Re: if ((read_c0_prid() & 0xff) >= 0x0050) George99 (mehr als 1000 Beiträge seit 10.10.05) Diethilde schrieb am 21. September 2013 22:59 > Sagt dir MISRA-C etwas? Ich habe mir mal > http://portal.automotive-his.de/images/pdf/SoftwareTest/his_subset_misra_c_1.0.3.pdf angesehen, welches im Wiki-Artikel verlinkt ist. Größtenteils stehen da (banale) Selbstverständlichkeiten, tw. Anforderungen, die wohl dem begrenzten Speicher im Embedded-Bereich geschuldet sind und auch nur dort sinnvoll sind (keine Rekursion benutzen, best. library-Funktionen nicht benutzen) tw. völlig Unsinniges (kein break, goto, continue, keine Pointer-Arithmetik benutzen, auch wenn sie sinnvoll wären) Das, was von den Regeln sinnvoll ist, weiß sowieso jeder C-Programmierer, welche zusätzlichen Einschränkungen im Embedded-Bereich zu berücksichtigen sind, sollte auch ohne Regelsammlung klar sein und tw. ist es eben auch sinnlos.

Aus anderen Foren


Meine Erfahrungen mit MISRA sehen so aus: In den frühen 90ern habe ich mal eine Bastelei abgeliefert, die im Wesentlichen als Protokollumsetzer gearbeitet hat, das waren ein paar Zeilen Assembler und weil's eine Insellösung war, hat sich niemand drum geschert. Später wurde das Ding um einen weiteren Bus aufgestockt und ich hab's mit einem Pascal neu gemacht, hat auch niemanden gejuckt. Letztes Jahr mußte die Sache aus technischen Gründen nochmal erweitert komplett neu designt werden, also in C, weil ein zugekaufter Netzwerkstack integriert werden sollte. Bei der Abnahme sagte man mir alles schön und gut, aber ist es auch MISRA- konform? War mir völlig entgangen, aber Hausregel ist: Wenn C, dann nur MISRA. Hätte ich Pascal genommen, wärs ihnen wurscht gewesen, dann hätte ich aber den Stack selbst schreiben müssen. Natürlich war's nicht konform. Nach dem Reformat- Lauf kommen einem manchmal auch eigene Module seltsam vor, weil man's optisch einfach anders im Gedächtnis hat. Natürlich wurden auch etliche Konstrukte bemängelt, die aber einwandfrei funktioniert haben. Eine Totalkatastrophe war dann auch noch die zugekaufte Lib, wenn fremder Code MISRA- konform gemacht werden muß, muß man das ganze benörgelte Zeug auch verstehen. Also der Umbau hat fast nochmal soviel Zeit gekostet wie das erste Design, ohne daß das in irgendeiner Weise produktiv war oder bezahlt wurde. Deswegen bin ich erstmal sauer auf das Beharren auf MISRA. Ich bin seit 16 Jahren der Einzige, der an das Projekt hinpfuscht und wage zu behaupten, daß die Anlage durch MISRA weder wartbarer geworden ist noch an Stabilität gewonnen hat, an einigen Stellen sogar deutlich umständlicher. Die Frage müßte lauten, ob es hier jemanden gibt, der sagt, fremden Code kapier' ich viel schneller, wenn er MISRA- konform geschrieben ist, dann hätte es einen Nutzen.
Ans Eingemachte geht es aber, wenn man mit Funktionspointern herumhantiert. Ich habe so eine verkettete Eventhandlerliste implementiert, da wird alles als void* draufgeschoben, die aufzurufenden Funktionen (alle void(void)) und auch die Parameter als (void *) einer struct irgendwas. Jede aufgerufene Funktion holt sich aus der Liste den Pointer auf die Argumente und muß halt mit einem free() das Argumentepaket nach der Abarbeitung löschen, also eigentlich durchschaubar, aber nach MISRA stockverboten. Als Umgehungskonstrukt ist mir nur eingefallen, Event- IDs in eine Liste zu schieben und die über eine lange switch/case zu parsen. Vorher war's sowohl übersichtlicher als auch performanter. Glaube nicht, daß jemand nach der MISRA-Adaption sagen könnte: "Das kapier' ich schneller".