Mir wurde gesagt, dass der folgende Code bis C ++ 20 ein undefiniertes Verhalten aufweist:
int *p = (int*)malloc(sizeof(int));
*p = 10;
Ist das wahr?
Das Argument war, dass die Lebensdauer des int
Objekts nicht vor dem Zuweisen des Werts gestartet wird ( P0593R6 ). Um das Problem zu beheben, new
sollte die Platzierung verwendet werden:
int *p = (int*)malloc(sizeof(int));
new (p) int;
*p = 10;
Müssen wir wirklich einen Standardkonstruktor aufrufen, der trivial ist, um die Lebensdauer des Objekts zu starten?
Gleichzeitig hat der Code in reinem C kein undefiniertes Verhalten. Aber was ist, wenn ich einen int
in C-Code zuordne und ihn in C ++ - Code verwende?
// C source code:
int *alloc_int(void)
{
int *p = (int*)malloc(sizeof(int));
*p = 10;
return p;
}
// C++ source code:
extern "C" int *alloc_int(void);
auto p = alloc_int();
*p = 20;
Ist es noch undefiniertes Verhalten?
c++
malloc
undefined-behavior
c++20
anton_rh
quelle
quelle
int
? Nein. Fürstd::string
? Ja.int
, auch ja. Es ist nur so, dass es in der Praxis keine Probleme verursacht, wenn Sie es nicht tun. Dennstd::string
es wird offensichtlich Probleme verursachen.int *p = (int*)malloc(sizeof(int)); p = new(p) int;
? Ich habe einmal festgestellt, dass das Nichtzuweisen des Ergebnisses der Platzierung auch fatale Auswirkungen haben kann (obwohl es ein bisschen albern aussehen könnte).Antworten:
Ja. Technisch gesehen kein Teil von:
int *p = (int*)malloc(sizeof(int));
Erstellt tatsächlich ein Objekt vom Typ
int
, sodass die Dereferenzierungp
UB ist, da dort kein Objekt vorhanden istint
.Haben Sie müssen pro C ++ Objektmodell nicht definiertes Verhalten pre-C ++ 20 zu vermeiden? Ja. Wird ein Compiler tatsächlich Schaden anrichten, wenn Sie dies nicht tun? Nicht dass ich wüsste.
Ja. Vor C ++ 20 haben Sie noch
int
nirgendwo ein Objekt erstellt, also ist dies UB.quelle
int
im Beispiel eine Lagerung mit der richtigen Größe und Ausrichtung erhalten -int
dort beginnt die Lebensdauer des Objekts.Ja, es war UB. Die Liste der Möglichkeiten, wie eine
int
Dose existieren kann, wurde aufgezählt, und dort gilt keine, es sei denn, Sie halten Malloc für kausal.Es wurde allgemein als ein Fehler im Standard angesehen, der jedoch von geringer Bedeutung war, da die von C ++ - Compilern für dieses bestimmte UB-Bit vorgenommenen Optimierungen keine Probleme mit diesem Anwendungsfall verursachten.
Was die zweite Frage betrifft, schreibt C ++ nicht vor, wie C ++ und C interagieren. Jede Interaktion mit C ist also ... UB, auch bekannt als Verhalten, das vom C ++ - Standard nicht definiert wird.
quelle
extern "C"
Syntax zu haben.gcc -fno-strict-aliasing
oder standardmäßig MSVC). Wenn Sie "Implementierung definiert" sagen, müssen alle C ++ - Implementierungen eine Art und Weise definieren, in der sie mit einer C-Implementierung zusammenarbeiten. Daher ist es sinnvoll, die Implementierung vollständig zu überlassen, ob sie so etwas tun möchten oder nicht.