Als Einschränkung deklarierte Parameter und Compiler-Warnungen

Lesezeit: 4 Minuten

Benutzeravatar von jch
jch

Weder gcc 5 noch clang 3.6 geben Warnungen aus, wo die Beschränkungen der restrict Qualifier verletzt werden, selbst wenn mit aufgerufen wird -Wall. Betrachten Sie das folgende Codefragment:

extern void f(char *restrict p, char *restrict q);

void g(char *p)
{
    f(p, p);
}

Naiverweise hatte ich erwartet, dass die Verletzung statisch festgestellt werden kann, und das hatte ich erwartet -Wall würde eine Warnung aussprechen. Habe ich irgendwo eine Flagge übersehen oder gibt es ein Problem mit Warnungen, die ich nicht sehe?

  • Top-Level-Qualifier in einem Prototyp sind bedeutungslos (außer als Dokumentation); der Funktionskörper könnte immer noch als implementiert werden void f(char *p, char *q);. Anscheinend optimiert kein Compiler den aufrufenden Code basierend auf dem Vorhandensein von restrict entweder. Verwandter Thread

    – MM

    5. Juni 2015 um 4:14 Uhr

  • Anstelle eines tatsächlich kommentierenden Compiler-Entwicklers würde ich nur vermuten, dass niemand nach dem Feature gefragt hat und / oder kein Entwickler beschlossen hat, Zeit in die Implementierung zu investieren.

    – MM

    5. Juni 2015 um 4:21 Uhr

Benutzeravatar von jch
jch

Ab Version 8 gibt gcc eine hilfreiche Warnung für den obigen Code aus:

a.c: In function ‘g’:
a.c:5:5: warning: passing argument 1 to restrict-qualified parameter aliases with argument 2 [-Wrestrict]
     f(p, p);
     ^

Angesichts des Codes:

void test(int *restrict a, int *restrict b, int c)
{
  a[0] += b[c];
}

das einzige Szenario von der betroffen restrict Qualifikation wäre a==b+c; in diesem Fall der Zeiger in a würde verwendet werden, um ein Objekt zu modifizieren, auf das auch über einen nicht verwandten Zeiger zugegriffen wird b. In allen anderen Fällen würde dies ohne definiert werden restrictkein Objekt, auf das über zugegriffen wird a würde auch über zugreifen bnoch umgekehrt.

Ein Compiler, der erkennen konnte, dass eine Funktion übergeben wurde restrict– Qualifizierte Zeigerargumente, die sie unter Verstoß gegen die damit verbundenen Regeln verwenden, könnten hilfreich vor einem solchen Verstoß warnen, aber ein Compiler, der nicht in eine Funktion sehen kann, hätte keine Möglichkeit zu wissen, welche Kombinationen von Argumenten gültig oder ungültig wären.

  • union { struct { char d; int e; } f; int g } h Und test(&h.f.e, &h.g, 0) ist ein kompliziertes Szenario, das auch bei Testparametern beeinflusst werden kann a==b+c ist nicht wahr.

    – chux – Wiedereinsetzung von Monica

    29. August 2018 um 2:29 Uhr

  • @chux: Abschnitt 6.5p7 des N1570-Standardentwurfs verzichtet (IMHO absichtlich) auf die Gewährung Decke Berechtigung zum Zugriff auf ein Aggregat mit beliebigen Lvalues ​​des Mitgliedstyps, mit oder ohne restrict. Dies ist dann sinnvoll, wenn Zugriffe über einen von einem Aggregat abgeleiteten Lvalue manchmal (für Zwecke von 6.5p7) als über den Aggregattyp statt über den Elementtyp erkannt werden. Da der Standard nicht sagt, wann Implementierungen eine solche Assoziation erkennen sollten, handelt es sich vermutlich um ein Problem der Implementierungsqualität.

    – Superkatze

    29. August 2018 um 15:18 Uhr

  • @chux: Der geschriebene Code würde in dem von Ihnen beschriebenen Fall eindeutig UB aufrufen, da die Operationen fortgesetzt werden a[0] Und b[c] werden nur wann sequenziert b[c] Und a[0] Identifizieren Sie dasselbe vollständige Objekt und nicht zwei teilweise überlappende Objekte. Wenn test geändert wurden int temp[b]c[; a[0]+=temp;kann ein solcher Code definiert werden oder nicht, abhängig davon, ob eine Operation auf dem Heap-Speicher, die einen von einem Aggregat abgeleiteten lvalue verwendet, so angesehen wird, dass der effektive Typ ausschließlich auf der Grundlage des abgeleiteten Typs oder des Aggregattyps festgelegt wird.

    – Superkatze

    29. August 2018 um 15:27 Uhr

  • Die derzeitige Praxis scheint zu sein, dass Operationen auf dem Heap-Speicher über lvalues, die von einem Aggregat abgeleitet werden, zumindest manchmal für die Zwecke der Regeln für den effektiven Typ so angesehen werden, als ob sie unter Verwendung des Aggregattyps ausgeführt würden; Angesichts des Fehlens einer pauschalen Berechtigung für den Zugriff auf Aggregate über Lvalues ​​vom Mitgliedstyp glaube ich nicht, dass der Standard irgendwelche Anforderungen an das Verhalten des Codes in “Überschneidungsszenarien” stellen würde.

    – Superkatze

    29. August 2018 um 15:30 Uhr

  • restrict Implikationen lassen sich nur schwer abschließend zusammenfassen. Danke für die Info.

    – chux – Wiedereinsetzung von Monica

    29. August 2018 um 15:49 Uhr

Der restrict Das Schlüsselwort ist eine ausdrückliche Zusicherung des Programmierers, dass die fraglichen Zeiger keinen Alias ​​verwenden. Im Wesentlichen ermöglicht es dem Compiler, die Aliasanalyse für diese Zeiger wegzulassen, da der Programmierer bereits die vermutete Antwort geliefert hat. Dies ermöglicht nicht nur eine bessere Optimierung, sondern kann auch Kompilierzeit sparen. In großen Programmen kann die Analyse ziemlich teuer sein, also ist das für sich schon eine große Sache.

Ich glaube also, die Antwort auf Ihre Frage lautet: “Die Compiler suchen nicht, weil der Code ihnen sagt, dass sie sich nicht darum kümmern sollen.”

  • Das beantwortet meine Frage nicht wirklich. Ich würde erwarten, dass der Compiler mich warnt, wenn Programmierfehler leicht zu erkennen sind.

    – jch

    5. Juni 2015 um 0:14 Uhr

1443560cookie-checkAls Einschränkung deklarierte Parameter und Compiler-Warnungen

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

Privacy policy