2012-10-31 3 views
14

私は2つのコードブロックに関するnew[]delete[]ありますp = new string [0]およびp = new int [0]の後、delete [] pのときに文字列バージョンがクラッシュする理由を教えてください。

1)

#include <string> 

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

    return 0; 
} 

2)この場合、私は単に私の質問があるstd::string

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

    delete[] p; 

    return 0; 
} 

int

を変更します。

なぜ最初のプログラムは、(Linux環境での)次のメッセージでクラッシュ:

Segmentation fault (core dumped) 

しかし、第2のプログラムがエラーなしでうまく動作しますか?

EDIT

コンパイラ:g++ (Ubuntu/Linaro 4.7.2-2ubuntu1) 4.7.2

私はちょうどそれをコンパイルするために引数なしg++を使用しています。

コンパイラのバグであれば、標準に従ってクラッシュするかどうかは問題ですか?

+2

は、それはここでクラッシュしない – Andrey

+1

コンパイラのバグのように見えます。どのコンパイラを使用していますか(正確なバージョンで)、どのようにコンパイルしていますか? – amaurea

+1

g ++(4.7と4.8)でクラッシュし、clangでクラッシュしません。私はg ++バグだと思う。 – kennytm

答えて

13

これはgccバグです。 new[]式全体が無視され、pが初期化されなくなり、次にdelete[]がクラッシュする初期化されていないポインタになります。 「P」、明らかに間違っているこの機能

に初期化されていない使用されている:我々は-Wallしてプログラムをコンパイルする場合、それは

警告があることを警告します。式new X[0]は、C++ 03とC++ 11(§5.3.4/ 7)の両方でよく定義されています。これはclangで正しく動作するため、唯一の結論はgccバグです。


除去・オブnew[]バグはのみ構築されるタイプは、任意の非自明なコンストラクタを持っているときに存在します。そして、セグメンテーションフォールトには型がデストラクタを持っているので、delete[]はその初期化されていないポインタを逆参照する必要があるからです。したがってstd::stringではクラッシュしますが、intは些細でstd::stringではないため、intではクラッシュしません。


これは、式は直接0に評価することはできないように、中間変数を使用することで回避することができます。

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

ライブワークスペースには、元のOPコード(警告+クラッシュ)、この回避策(警告なし、クラッシュなし)、 'size_t const length = 0;'(警告、クラッシュはありません)。私は*愛* gcc ... –

関連する問題