メインコンテンツ

ポインターの無効な削除

new を使用して対応する割り当てを行っていないポインターに対して delete を使用して割り当てを解除する

説明

この欠陥は、以下の場合に発生します。

  • delete 演算子を使用してメモリのブロックを解放したが、そのメモリが以前に new 演算子を用いて割り当てられていなかった。

  • 単一オブジェクト表記で delete 演算子を使用してメモリのブロックを解放したが、そのメモリが以前に new 演算子を用いて配列として割り当てられていた。

この欠陥は C++ ソース ファイルに対してのみ適用されます。

リスク

リスクは問題の原因によって異なります。

  • delete 演算子はヒープに割り当てられたメモリのブロックを解放します。以前に割り当てていないヒープ上の位置にアクセスしようとすると、セグメンテーション違反が発生する可能性があります。

  • new の配列表記で以前に割り当てたポインターに対して、delete 演算子の単一オブジェクト表記を使用すると、動作が未定義になります。

この問題により、他のコーディング エラーが明らかになる場合があります。たとえば、delete 演算子または前の new 演算子を別のポインターに対して使用する必要があった可能性があります。

修正方法

修正方法は問題の原因によって異なります。

  • ほとんどの場合、delete ステートメントを削除することによって問題を修正できます。new 演算子を使用してポインターにヒープのメモリが割り当てられていない場合、delete を使用してこのポインターを解放する必要はありません。単に必要に応じてポインターを再利用するか、スコープの終了時にオブジェクトが破棄されるままにしておくことができます。

  • newdelete の表記が一致していない場合、その不一致を修正します。たとえば、単一のオブジェクトを割り当てて、その割り当てを解除する場合は、次の表記を使用します。

    classType* ptr = new classType;
    delete ptr;

    配列オブジェクトを割り当てて、その割り当てを解除する場合は、次の表記を使用します。

    classType* p2 = new classType[10];
    delete[] p2;

この問題によって、間違ったポインターに対して delete または new を使用するなどのコーディング エラーが明らかになった場合は、そのエラーを修正します。

すべて展開する

void assign_ones(void)
{
    int ptr[10];

    for(int i=0;i<10;i++)
        *(ptr+i)=1;  

    delete[] ptr;   
}

ポインター ptr は、delete 演算子を使用して解放されています。しかし、ptr は動的に割り当てられていないメモリの場所を指しています。

修正: ポインターの割り当て解除を削除

配列 ptr の要素数がコンパイル時にわかっている場合、1 つの修正方法として、ポインター ptr の割り当て解除を削除することができます。

void assign_ones(void) 
{
    int ptr[10];

    for(int i=0;i<10;i++)
        *(ptr+i)=1;  
}
修正 — ポインターの割り当てを追加

配列の要素数がコンパイル時にわかっていない場合、1 つの修正方法として、new 演算子を使用して配列 ptr に動的にメモリを割り当てることができます。

void assign_ones(int num) 
{
    int *ptr = new int[num]; 

    for(int i=0; i < num; i++)
        *(ptr+i) = 1;

    delete[] ptr;
   }
int main (void)
{
    int *p_scale = new int[5];

    //more code using scal

    delete p_scale;
}

この例では、new int[5] を使用して、p_scale がサイズ 5 の配列に初期化されます。しかし、p_scale は、delete[] ではなく delete によって削除されています。newdelete のペアが対応していません。配列を削除する場合は、大かっこを伴わない delete は使用しないでください。

修正 — deletenew に対応させる

1 つの修正方法として、大かっこを追加して、delete が宣言 new [] と整合性をもつようにします。

int main (void)
{
    int *p_scale = new int[5];

    //more code using p_scale

    delete[] p_scale;
}
修正 — newdelete に対応させる

別の修正方法として、p_scale の宣言を変更します。p_scale を、サイズ 5 の配列ではなく 5 という数値として初期化する場合、異なる構文を使わなければなりません。これを修正するには、初期化での大かっこを小かっこに変更します。delete ステートメントはそのままにしておきます。

int main (void)
{
    int *p_scale = new int(5);

    //more code using p_scale

    delete p_scale;
}

結果情報

グループ: 動的メモリ
言語: C++
既定値: 手書きコードはオン、生成コードはオフ
コマンド ライン構文: BAD_DELETE
影響度: High

バージョン履歴

R2013b で導入