2010-08-09 6 views
10

Ich arbeite gerade an einem C-Projekt, das in verschiedenen Gebäudeumgebungen relativ portabel sein soll. Das Projekt zielt auf POSIX-konforme Systeme in einer gehosteten C-Umgebung ab.Strenger ISO-C-Konformitätstest

Eine Möglichkeit, ein gutes Maß an Portabilität zu erreichen, ist die Kodierung unter Einhaltung eines gewählten Standards, aber es ist schwierig zu bestimmen, ob eine bestimmte Übersetzungseinheit ISO-konform ist. Zum Beispiel könnte sie eine Übersetzung verletzen Grenzen, oder es könnte auf ein undefiniertes Verhalten, ohne jede diagnostische Nachricht von der Kompilierumgebung verlassen werden. Ich bin mir nicht einmal sicher, ob es möglich ist, die strenge Konformität großer Projekte zu überprüfen.

Vor diesem Hintergrund ist es ein Compiler, Werkzeug oder Verfahren für strenge ISO C Konformität unter einem bestimmten Standard (zB C89 oder C99) eine Übersetzungseinheit zu testen?

Jede Hilfe wird geschätzt.

Antwort

4

Es ist im Allgemeinen nicht möglich, ein nicht definiertes Laufzeitverhalten zu finden. Betrachten wir zum Beispiel

void foo(int *p, int *q) 
{ 
    *p = (*q)++; 
    ... 

die, wenn p == q nicht definiert ist. Ob das passieren kann, lässt sich nicht im Voraus bestimmen, ohne das Halteproblem zu lösen.

(Edited Fehler caf zu beheben aufgezeigt. Danke, caf.)

+0

Ihr Beispiel ist fantastisch. Ich habe nie über solche einfachen Zeigerausdrücke nachgedacht. Ich glaubte, dass jeder dieser undefinierten Zustand zu Beginn der Untersuchung entdeckt werden konnte. – alecov

+3

Ihr Beispiel ist in Ordnung, auch wenn 'p == q' - vielleicht meintest du' * p = (* q) ++ ', was undefiniert ist, wenn' p == q'? – caf

3

Nicht wirklich. Der C-Standard legt keine absoluten Mindestgrenzen für Übersetzungseinheiten fest, die akzeptiert werden müssen. Als solches würde eine vollkommen genaue checker trivial zu schreiben, aber völlig nutzlos in der Praxis:

#include <stdio.h> 

int main(int argc, char **argv) { 
    int i; 
    for (i=1; i<argc; i++) 
     fprintf(stderr, "`%s`: Translation limit (potentially) exceeded.\n", argv[i]); 
    return 0; 
} 

Ja, das lehnt alles, egal wie trivial. Das entspricht dem Standard. Wie gesagt, es ist in der Praxis absolut nutzlos. Leider können Sie nicht wirklich viel besser machen - wenn Sie sich entscheiden, auf eine andere Implementierung zu portieren, könnten Sie auf ein seltsames Ressourcenlimit stoßen, das Sie noch nie zuvor gesehen haben, also jeden Code, den Sie schreiben (bis zu einem einschließlich " hallo world ") könnte möglicherweise ein Ressourcenlimit überschreiten, obwohl es von Dutzenden oder sogar Hunderten von Compilern auf/für viel kleinere Systeme erlaubt ist.

Edit:

Warum ein „Hallo Welt“ Programm nicht streng

Zuerst konform ist, ist es wert, wieder unter Angabe der Definition von „streng konform“: „Eine streng konformen Programm verwenden soll nur diejenigen Merkmale der Sprache und Bibliothek, die in dieser Internationalen Norm festgelegt sind.2) Sie darf keine Ausgabe erzeugen, die von einem nicht spezifizierten, undefinierten oder implementationsdefinierten Verhalten abhängt, und darf keine minimale Implementierungsgrenze überschreiten. "

Es gibt tatsächlich eine Nummer Gründe "Hallo, Welt" ist nicht streng konform. Erstens, wie oben angedeutet, sind die Mindestanforderungen für die Umsetzungsgrenzen völlig bedeutungslos - obwohl es einige Programm geben muss, das bestimmte Grenzen erfüllt, die akzeptiert werden, kein anderes Programm muss akzeptiert werden, auch wenn es nicht ' Ich komme sogar einer dieser Grenzen nahe. In Anbetracht der Art und Weise, in der die Anforderung formuliert wird, kann (bestenfalls) in Frage gestellt werden, ob es ein Programm gibt, das eine Mindestumsetzungsgrenze nicht überschreitet, da der Standard keine Mindestumsetzungsgrenzen definiert.

Zweitens, während Phase 1 der Übersetzung: "Physikalische Quelldatei Multibyte-Zeichen werden in einer Implementierung definiert, um den Quellzeichensatz zugeordnet ..." (§5.1.1.2/1). Seit "Hallo, Welt!" (oder welche Variante Sie auch bevorzugen) wird als String-Literal in der Quelldatei angegeben, sie kann in einer implementierungsdefinierten Weise dem Quellzeichensatz zugeordnet werden. Eine Implementierung kann frei entscheiden, dass String-Literale (für ein idiotisches Beispiel) ROT13-kodiert sind und solange diese Tatsache richtig dokumentiert ist, ist sie vollkommen legitim.

Drittens wird der Ausgang normalerweise über stdout geschrieben. stdout ist ein Text-Stream. Gemäß dem Standard: "Zeichen müssen möglicherweise bei Eingabe und Ausgabe hinzugefügt, geändert oder gelöscht werden, um unterschiedlichen Konventionen für die Darstellung von Text in der Host-Umgebung zu entsprechen. Daher muss keine Eins-zu-Eins-Entsprechung zwischen den Zeichen bestehen in einem Strom und diejenigen in der äußeren Darstellung. " (§7.19.2/2) Als solche könnte eine Implementierung (zum Beispiel) eine Huffman-Komprimierung an der Ausgabe (am Montag, Mittwoch oder Freitag) durchführen.

So haben wir (mindestens) drei verschiedene Punkte, an denen die Ausgabe von einem "Hallo, Welt!" hängt von implementationsdefinierten Merkmalen ab - von denen jede verhindern würde, dass sie die Definition eines streng übereinstimmenden Programms erfüllt.

+0

Dies entspricht nicht dem Standard. Siehe §5.2.4.1 Übersetzungsbeschränkungen. –

+0

@ Stephen: Ja, ist es. Die Anforderung lautet: "Die Implementierung muss in der Lage sein, mindestens ein Programm zu übersetzen und auszuführen, das mindestens eine Instanz jeder der folgenden Grenzen enthält:". Nur ein * spezifisches Programm - und es scheint nicht einmal eine Anforderung zu sein, das Programm zu dokumentieren. Jede mögliche Eingabe kann fehlschlagen, mit Ausnahme einer bestimmten, die nicht identifiziert werden muss ... –

+1

aus der Norm ISO C99, §4 Konformität: "Ein streng konformes Programm darf nur die Merkmale der Sprache und der Bibliothek verwenden, die in diesem Dokument angegeben sind Internationaler Standard. Er soll keine Ausgabe erzeugen, die von einem nicht spezifizierten, undefinierten oder implementationsdefinierten Verhalten abhängt, und darf keine minimale Implementierungsgrenze überschreiten. " Warum sollte also eine offensichtlich einfache Implementierung des Hello World-Programms in diesem Fall nicht streng konform sein? – alecov

0

gcc hat Warnstufen, die versuchen, verschiedene Aspekte der ANSI-Konformität festzulegen. Aber das ist nur ein Anfang.

0

Sie mit gcc -std=c99 beginnen könnte, oder gcc -ansi -pedantic.

0

Viel Glück damit. Versuchen Sie, vorzeichenbehaftete Ganzzahlen zu vermeiden, denn:

int f(int x) 
{ 
return -x; 
} 

kann UB aufrufen.