Warum können wir mit malloc keine trivial konstruierbaren Objekte erstellen, wenn der triviale Standardkonstruktor keine Aktion ausführt?

14

Ich habe Schwierigkeiten, den folgenden Absatz zu verstehen, der aus der Referenz über den trivialen Standardkonstruktor zitiert wird . Ich habe nach Stackoverflow gesucht, aber immer noch keine klare Antwort erhalten. Also bitte helfen.

Ein trivialer Standardkonstruktor ist ein Konstruktor, der keine Aktion ausführt. Alle mit der C-Sprache kompatiblen Datentypen (POD-Typen) sind trivial standardmäßig konstruierbar. Im Gegensatz zu C können Objekte mit trivialen Standardkonstruktoren jedoch nicht durch einfaches Neuinterpretieren eines entsprechend ausgerichteten Speichers erstellt werden, z. B. der mit std :: malloc zugewiesene Speicher. Placement-new ist erforderlich, um ein neues Objekt formal einzuführen und potenzielles undefiniertes Verhalten zu vermeiden.

Wenn der triviale Standardkonstruktor nichts tut, warum können wir dann den Speicher nicht neu interpretieren und so tun, als gäbe es ein Objekt mit dem angegebenen Typ? Könnten Sie bitte einige Beispiele für das mögliche undefinierte Verhalten nennen , das dies verursachen würde?

Liu Sha
quelle
Die wichtigste Aufgabe eines Compilers besteht nicht darin, den Quellcode zu kompilieren, sondern möglicherweise ungültigen Code abzulehnen. Dies ist nicht möglich, wenn Sie malloc () verwenden.
Hans Passant
6
Der Grund ist sehr einfach. Je weniger Möglichkeiten der Programmierer hat, verrückte Dinge zu tun, desto mehr Möglichkeiten gibt es für den Compiler, verrückte Dinge zu tun (aggressive Optimierungen).
n. 'Pronomen' m.
1
Aus ähnlichen Gründen kann man das nicht einfach *reinterpret_cast<float*>(&someNonFloatObject) = 0.1f;. C ++ hat ein Konzept von Objekten und Objektlebensdauern, das auf dem abstrakten Computer angegeben ist. Nur weil es keine CPU-Anweisung zum Erstellen eines Objekts aus dem Speicher gibt, bedeutet dies nicht, dass es auf dem abstrakten Computer keinen Unterschied gibt.
Max Langhof
1
@HansPassant Ein Compiler, der den gesamten Code ablehnt, lehnt den gesamten ungültigen Code ab. Auf jeden Fall ist es nicht die Aufgabe des Copilers, Programme mit UB abzulehnen.
n. 'Pronomen' m.
1
stackoverflow.com/q/52154744
StoryTeller - Unslander Monica

Antworten:

7

P0593R5 gibt dieses Beispiel:

struct X { int a, b; };
X *make_x() {
  X *p = (X*)malloc(sizeof(struct X));
  p->a = 1;
  p->b = 2;
  return p;
}

und erklärt:

Bei der Kompilierung mit einem C ++ - Compiler weist dieser Code ein undefiniertes Verhalten auf, da p-> a versucht, in ein int-Unterobjekt eines X-Objekts zu schreiben, und dieses Programm weder ein X-Objekt noch ein int-Unterobjekt erstellt hat.

Per [intro.object] p1,

Ein Objekt wird durch eine Definition, durch einen neuen Ausdruck erstellt, wenn das aktive Mitglied einer Union implizit geändert wird oder wenn ein temporäres Objekt erstellt wird.

... und dieses Programm hat keines dieser Dinge getan.

In der Praxis funktioniert dies und die UB-Situation wird mehr als ein Defekt in der Norm als alles andere angesehen. Das gesamte Ziel des Papiers ist es, einen Weg vorzuschlagen, um dieses Problem und ähnliche Fälle zu beheben, ohne andere Dinge zu beschädigen.

Ein Programmierer
quelle
1

Aus "Reinheitsgründen".

Die Alternative und der tatsächliche Status Quo bestand darin, dass jeder Speicherbereich alle Objekte enthält, die gleichzeitig in diesen Speicher passen. Einige Ausschussmitglieder sind unruhig mit dem Status quo und eine Menge Leute fürchteten den Begriff der mit unendlich viele Objekte an der gleichen Stelle (in einem virtuellen, nicht initialisierten Zustand).

Niemand hat jemals ein logisches Problem mit unendlich vielen Objekten in einer Speicherregion aufzeigen können.

Da es in verschiedenen Abschnitten des Standards widersprüchliche Aussagen gab, beschlossen die Ausschussmitglieder, einen der schlimmsten Teile des Standards ernst zu nehmen.

Die Verwendung von String-Literalen ist strengstens untersagt, wenn Sie diesen einen Teil des Standards wirklich ernst nehmen.

Neugieriger
quelle
Die Verwendung von String-Literalen ist in der Tat strengstens untersagt. Es gibt ein ähnliches CWG-Problem bei type_infoObjekten. Haben Sie über String-Literale berichtet?
Sprachanwalt