Gibt es eine Möglichkeit, mechanisch festzustellen, welche Operationen auf einem verschobenen Objekt sicher sind?

8

Die Beweglichkeit ermöglicht eine große Klasse von Optimierungen. Aber es fühlt sich so an, als würde es ein Loch in die statische Sicherheit von Programmen schlagen:

Nach einer Verschiebung verbleibt das Quellobjekt in einem gültigen, aber nicht spezifizierten Zustand, in dem einige Operationen legal sind, einige jedoch nicht. (Siehe insbesondere diese SO-Frage für Diskussionen zu diesem Thema). Es scheint, dass diese Liste von Operationen, obwohl sie von jedem Typ abhängt, zur Kompilierungszeit bekannt sein kann. Der Compiler warnt jedoch nicht vor falscher Verwendung von bewegten Objekten (wie diese andere SO-Frage diskutiert). p>

Es fühlte sich an wie C ++ - Philosophie, sich auf den Compiler zu verlassen, um so viel wie möglich zu validieren (von dem, was statisch bekannt ist), wobei eines von vielen Beispielen die const-Korrektheitsdurchsetzung ist. Es scheint jedoch, dass ein Objekt, das von einem Objekt verschoben wurde, in gefährlicher Weise verwendet werden kann, ohne dass der Compiler versucht (oder irgendeinen Mittelwert), sie zu fangen.

Gibt es tatsächlich einen Mechanismus, der eine bessere Diagnose durch den Compiler ermöglicht? Wenn nicht, warum gibt es kein neues Qualifikationsmerkmal, das auf Methoden angewendet werden kann, die auf ein verschobenes Objekt angewendet werden können, oder ein anderer Mechanismus, der äquivalente statische Verifizierungen zulässt?

    
Ad N 16.10.2015, 09:02
quelle

5 Antworten

4
  

Die Beweglichkeit ermöglicht eine große Klasse von Optimierungen. Dennoch fühlt es sich so an, als würde es ein Loch in die statische Sicherheit von Programmen schlagen.

Ja, tut es.

  

Es scheint, dass diese Liste von Operationen, obwohl sie von jedem Typ abhängt, zur Kompilierungszeit bekannt sein kann.

Aber nicht vom Compiler im Allgemeinen.

  

Der Compiler warnt jedoch nicht vor falscher Verwendung von verschobenen Objekten.

Es wäre aber nett!

Nein, Sie werden sich auf die Dokumentation verlassen müssen. Oder tue einfach, was ich tue, und benutze das Objekt nie wieder , wenn du von einem lvalue wegbewegst , außer du hast einen streng kontrollierten Bereich und eine offensichtliche "Reset" -Operation auf dem Objekt unmittelbar danach.

Natürlich zeigt das Verschieben von einem rvalue dieses Problem nicht.

    
quelle
1

Ich denke, es ist unwahrscheinlich, dass ein zusätzlicher Qualifier zum Standard für einen solchen Edge-Fall hinzugefügt wird.

Eine Möglichkeit wäre, Ihre Funktionsdeklarationen mit #pragma supports_moved_from oder etwas zu markieren und dann ein Tool zur statischen Analyse zu erstellen, um Aufrufe von Funktionen auf möglicherweise verschobenen Objekten zu erkennen und zu prüfen, ob sie markiert wurden.

Sie könnten dafür wahrscheinlich eine der vielen Clang Werkzeugschnittstellen verwenden.

    
TartanLlama 16.10.2015 09:22
quelle
1

Gegeben n4034 und std::experimental::optional , Sie können sich ein optionales Element vorstellen, das eine Operation zum Verschieben von und zum leeren Objekt enthält.

Ein solches Objekt wäre nach dem Verschieben in einem klaren "nicht gültigen" Zustand.

Sie würden immer noch einen Weg brauchen, um die Zustandsänderung so auszudrücken, dass C ++ Compiler sie statisch überprüfen könnten.

Theoretisch kann eine Sprachenerweiterung, die es Operationen ermöglicht, den Typ einer Variablen während ihrer Lebensdauer zu ändern, zu C ++ hinzugefügt werden, ebenso wie Typanmerkungen; dann könnte ein Wert für das Verschieben von from geändert werden, damit diese Annotation angewendet wird, und Operationen, die für einen Wert für das Verschieben von from ungültig sind, würden Compilerfehler auslösen.

.reset() style-Operationen sind möglicherweise sowohl für Werte, die von "from-moved-from" -Werten als auch für Werte für nicht-verschobene-from-Werte verwendet werden, und in beiden Fällen die Annotationen in "normal".

Ich bin kein Experte, aber ich glaube, dass Rust versucht, etwas Ähnliches zu tun, um ähnliche Probleme zu lösen; Der Programmierer muss dem Typensystem beweisen, dass bestimmte Operationen gültig sind.

Dies ist auch vergleichbar mit der neuesten Arbeit zur Lecksuche / ungültigen statischen Zeigererkennung.

    
Yakk 16.10.2015 14:05
quelle
0

Immer wenn eines Ihrer vorhandenen Objekte in einem Zustand ist, in dem einige Operationen erlaubt sind und andere nicht, haben Sie wahrscheinlich ein Designproblem. In der Regel ist dies ein starkes Zeichen für einen Verstoß gegen das Prinzip der einheitlichen Verantwortung. Zumindest sollten alle Mitgliedsfunktionen in jedem Fall ein definiertes Verhalten haben - vielleicht wird es eine Ausnahme auslösen.

Wenn Sie also fragen, welche Operationen Sie an einem Objekt in einem bestimmten Zustand aufrufen dürfen, überdenken Sie Ihr Design.

    
cdonat 16.10.2015 09:17
quelle
0
  

Gibt es tatsächlich einen Mechanismus, der eine bessere Diagnose durch den Compiler ermöglicht?

Es gibt nichts, was einen Compiler daran hindern könnte, eine statische Analyse des Missbrauchs von verschobenen Objekten zu versuchen: Es ist in etwa dasselbe wie das erneute Markieren des Objekts in einem nicht initialisierten Zustand, und viele Compiler geben eine Warnung für die Verwendung von Variablen aus dass sie nicht selbstbewusst sind, wurden initialisiert.

Das heißt, der Standard schreibt diese Art von Diagnose normalerweise nicht vor: Sie sind in der Kompilierzeit möglicherweise teuer, sie sind in der Regel nicht perfekt (z. B. wenn Sie einen nicht const Verweis auf ein verschobenes Objekt übergeben zu einer Funktion, die Sie aufrufen, und die Implementierung ist nicht in der Übersetzungseinheit (dh für den Compiler nicht sichtbar) - sie kann nicht wissen, ob das verschobene Objekt ohne irgendeine Art von vorheriger Zuweisungs- / Rücksetzoperation zu a "verwendet" werden könnte bedeutungsvoller Wert.

Wenn Sie eine nicht const -Referenz an ein beliebiges Objekt an eine Funktion übergeben, für die die Definition nicht bekannt ist, können Sie nicht wissen, ob dieses Objekt aus der Funktion heraus bewegt werden kann.

  

Wenn nicht, warum gibt es kein neues Qualifikationsmerkmal, das auf Methoden angewendet werden kann, die für ein verschobenes Objekt verwendet werden können, oder ein anderer Mechanismus, der äquivalente statische Verifizierungen zulässt?

Die Quintessenz ist, dass es ein paar Mal relativ einfach für einen Compiler ist zu erkennen, dass ein Objekt ein verschobener Zustand ist, und oft, wenn es nicht möglich ist. Ein Qualifikationsmerkmal könnte nützlich sein, aber zweifellos würde es für viele Leute als Garantie dafür gehalten werden, dass ein verschobenes Objekt nicht missbraucht werden kann, und es würde einen konstanten Strom von verwandten Fragen und Fehlern geben. Ohne eine Best-Effort-Verifizierung - und der Programmierer versteht eindeutig, dass es in seiner Verantwortung liegt, ein Problem zu analysieren - kann es manchmal besser sein, Entwicklern ein falsches Gefühl der Sicherheit zu geben.

    
Tony Delroy 16.10.2015 10:28
quelle

Tags und Links