2016-10-30 4 views
3

は、次のコードを考えてみましょう:C++で[]を削除します。

int main() 
{ 
    char* str = new char; 
    str[0] = 'a'; 
    delete[] str; //Notice the [] 
} 

それはコンパイル、実行し、何が(VC15とg ++)がクラッシュ しかし、私はvalgrindのをはっきりと見ることができる1つのメモリリークを持っています。

私はしかし、次のコードを実行した場合:

#include <iostream> 

class Foo{ 
public: 
    Foo(){ 
     std::cout << "Foo::Foo" << std::endl; 
    } 
    ~Foo(){ 
     std::cout << "Foo::~Foo" << std::endl; 
    } 
}; 

int main() 
{ 
     Foo* foo = new Foo; 
     delete[] foo; 
     return 0; 
} 

を私は(〜20 D'TORS呼び出し後)は、Windows上で動作しているときデストラクタ呼び出しの無限ループを取得し、およびLinuxでの無効なポインタエラー。

私が理解できないことは、2つの違いがある理由です。 new charまたはクラッシュで無限ループが発生するのはなぜですか?

+3

未定義の動作です。この種のバグを持つコードからは特に何も期待できません。 – juanchopanza

+0

'undefined'とは何ですか?ポインタのdelete []? – ZivS

+1

はい、 'new []'で割り当てられていないものに対して 'delete []'を呼び出します。 – juanchopanza

答えて

2

new[]を使用して割り当てられたポインタのみを使用してdelete[]を使用します。声明char* str = new char;あなたは、単一のcharへのポインタを取得して

  • 問題あなたの最初のコードスニペットで

    。新しいタイプのタイプはchar*と一致します。

  • しかし、あなたのdelete[]は、charの配列へのポインタを期待するので、あなたは、配列

2番目のコードスニペットは、まったく同じ問題を抱えているではない何かを削除未定義の動作(UB)を取得します。 UBは定義されておらず、不思議で説明できない結果をもたらす可能性があります。

解決方法

どちらか一つの要素は、単一要素の割り当てに削除使用:

Foo* foo = new Foo; 
    delete foo; 

ORアレイは、アレイの割り当てに削除使用:

Foo* foo = new Foo[1]; 
    delete[] foo; 

またはそれ以上:/任意の新しい取り除きますあなたは配列の代わりにベクトルを使い、使いたいと思っています。

+0

このステートメントの仕様を指すことができますか? – ZivS

+0

@ZivS削除の代わりに削除を使用[] –

+0

@ZivS:http://eel.is/c++draft/expr.delete#2 – krzaq

1

ようにするには、new[]が割り当てられていないとnullないたポインタにdelere[]を呼び出して、短いです未定義

私はcppreference.comから引用:[削除によって

と呼ばれます] - 式を使用して、以前にオブジェクトの配列に割り当てられたストレージを解放します。ptrがNULLポインタ であるか、または以前に新たなオペレータまたはオペレータ 新[]は(size_t、STD :: nothrow_tの標準 ライブラリ実装から得られたポインタでなければ、この関数の標準 ライブラリ実装の動作は未定義である )。

関連する問題