2012-10-31 13 views
14

Ich habe zwei Codeblöcke über new[] und delete[]:Nach p = neuer String [0] und p = neuer int [0], warum die String-Version beim Löschen [] p abstürzt?

1)

#include <string> 

int main() 
{ 
    std::string *p = new std::string[0]; 
    delete[] p; 

    return 0; 
} 

2) In diesem Fall ich nur std::stringint

int main() 
{ 
    int *p = new int[0]; 

    delete[] p; 

    return 0; 
} 

Meine Frage ist, ändern:

Warum? die ersten Programmabstürze mit der folgenden Meldung (in Linux-Umgebung):

Segmentation fault (core dumped) 

Aber das zweite Programm funktioniert gut ohne Fehler?

EDIT

Compiler: g++ (Ubuntu/Linaro 4.7.2-2ubuntu1) 4.7.2

benutze ich nur g++ ohne Argument, es zu kompilieren.

Wenn es ein Compiler Bug ist, sollten sie abstürzen oder nicht nach dem Standard?

+2

Sieht aus wie ein Compiler Fehler – Andrey

+1

Es hier nicht abstürzen. Welchen Compiler benutzen Sie (mit genauer Version) und wie kompilieren Sie ihn? – amaurea

+1

Absturz mit g ++ (4.7 & 4.8), stürzt nicht mit Klängen ab. Ich denke es ist ein g ++ Bug. – kennytm

Antwort

13

Dies sollte ein GCC-Bug sein. Das der gesamte new[] Ausdruck ignoriert wird und p uninitialisiert wird, und dann wir delete[] ein nicht initialisierter Zeiger, der abstürzt. Wenn wir das Programm mit -Wall kompilieren wird es Sie warnen, dass

Warnung: ‚p‘ in dieser Funktion nicht initialisierten verwendet wird

, die eindeutig falsch ist. Der Ausdruck new X[0] ist sowohl in C++ 03 als auch in C++ 11 (§5.3.4/7) wohldefiniert, und dies funktioniert korrekt in clang, also ist die einzige logische Schlussfolgerung, dass es ein gcc-Bug ist.


Die Eliminations-of- new[] Fehler existiert nur, wenn der Typ jedes nicht-triviale Konstruktor konstruiert werden. Und der segfault passiert, der Typ hat einen Destruktor, weil der delete[] dann diesen nicht initialisierten Zeiger dereferenzieren muss. Daher stürzt es für std::string aber nicht int ab, weil int trivial ist und std::string nicht ist.


Dies kann um unter Verwendung einer Zwischengröße gearbeitet werden, so dass der Ausdruck nicht auf 0 direkt ausgewertet werden können:

size_t length = 0; 
std::string* p = new std::string[length]; 
// ... 
delete[] p; 
+0

Ich bin überrascht, der Hack funktioniert ... Auf Liveworkspace habe ich 3 Verhaltensweisen: Original-OP-Code (Warnung + Absturz), diese Umgehung (keine Warnung, kein Absturz), mit 'size_t const Länge = 0;' (Warnung, kein Unfall). Ich * liebe * gcc ... –

Verwandte Themen