4

今日、EFNet C++ Wiki のヒープ破損に関する記事で、2 つのコードを見つけました。

void this_is_bad() /* You wouldn't believe how often this kind of code can be found */    
{    
    char *p = new char[5];    /* spend some cycles in the memory manager */    
    /* do some stuff with p */    
    delete[] p;      /* spend some more cycles, and create an opportunity for a leak */    
 }  

別の方法:

void this_is_good()    
{    
   /* Avoid allocation of small temporary objects on the heap*/   
   char p[5];    /* Use the stack instead */   
   /* do some stuff */  
}    

コードの最初の部分が適切と見なされない理由を理解するのに誰か助けてもらえますか?

4

4 に答える 4

7

を使用するchar* p場合は、ヒープに割り当てpているため、最後にヒープを削除する必要があります。との間char *pdeletedo some stuff with pのコードは例外をスローする可能性があり、pリークされます。

を使用する場合は、注意を払う必要がない方法でスタックにchar p[5]割り当てられ、コードが例外をスローした場合でも安全です。pdelete

void this_is_bad()   
{    
  char *p = new char[5]; //on the heap
  // What happens if I throw an unhandled exception here?
  delete[] p;  // I never get to delete p and it gets leaked
}  
于 2012-06-14T15:51:28.130 に答える
2

ヒープの代わりにスタックを使用する場合、現在の関数のスコープが失われると、メモリが復元されます。

newキーワードを使用すると、ヒープメモリが割り当てられます。newキーワードで割り当てられたメモリを削除することを忘れないでください。キーワードの後、newキーワードの前に例外がスローされた場合、例外がスローされた後deleteの時点で実行を再開できない可能性があるため、メモリリークが発生する可能性があります。

于 2012-06-14T15:51:44.797 に答える
2

これを行うための現在の最良の方法は次のとおりです。

 #include <vector>

 void this_is_great()
 {
     std::vector<char> myCharVec(5);

     // use myCharVec

 }  // when this function ends whether by return or by exception myCharVec is cleaned up

このように、ベクトル内のメモリ (「配列」と考えてください) はヒープ上にありますが、オブジェクトが存在し、いくつかのブックキーピングがスタック上にあり (大まかに言えば)、オブジェクトが破棄されると、そのヒープ メモリは自動的にクリーンアップされます。ガベージ コレクションのオーバーヘッドなどのないベクターのデストラクタ。

これは、いわゆるRAII イディオムです。

これがスタックに直接置くよりも好まれるもう 1 つの理由は、スタック上のバ​​ッファー オーバーラン (配列を扱うときによく発生する) は、メモリがヒープ上にある場合よりも壊滅的であり、検出が困難になる可能性があるためです。

于 2012-06-14T16:06:41.410 に答える
2

ヒープは共有メモリ リソースであり、プロセスの外部で (例に示されているようにメモリ マネージャーによって) 管理する必要があります。一方、スタックはプロセスによって管理され、メソッド内でスタックにプッシュされた変数は、メソッドが完了すると自動的に解放/ポップされます。これはクリーンで、事実上無料で、事実上絶対確実です。

これにより、メモリ リークが発生する可能性が回避されます。たとえば、'delete' に渡された領域が (たとえば、誤って ptr 値を再割り当てすることによって)、'new' 操作によって割り当てられたメモリと正確に一致しません。メソッド内で非統計変数を使用する場合、そうしない理由はありません。

参照: C++、フリーストアとヒープ

于 2012-06-14T16:08:15.200 に答える