2016-08-04 17 views
1
#include <iostream> 
#include <stdlib.h> 
#include <string.h> 
#include <map> 
using namespace std; 

char a[10]; 
map <string, char*> mm; 

void update(string s, char* b) 
{ 
    delete mm[s]; 
    mm[s] = b; 
} 
int main() 
{ 
    char* ptr = new char[100]; 
    char* ptr1 = new char[100]; 
    mm.insert(pair<string, char*>(string("abc"), ptr)); 
    update ("abc", ptr1); 

    delete ptr1; 
    return 0; 
} 

私のコードは多少このようです。キーを使用して値を削除しようとすると、Valgrindはリークを示します。マップからエントリを削除すると、Valgrindのリークが表示されます。

しかし、上記のコードを同じValgrindで試しても漏れがないことを示しています。このようなマップで削除を使用すると、そこに不利な点はありますか?イテレータを割り当てて、それを削除しようとしました

delete itr->second; 

これは問題なく動作しています。漏れはありません。最初の削除方法の問題は何ですか?

+0

をなぜあなたはすべての生のポインタがありますか? –

+2

あなたは正しい形式の削除を要求していません。 'delete []'ではなく、 'delete'でなければなりません。また、なぜこのようなコードを意図的に書くのでしょうか?単純に 'map 'ではないのですか? – PaulMcKenzie

+0

これは、学習目的のためのおもちゃのコードであり、本番では 'char * 'を使用しないことを期待しています。さもなければ 'delete ptr1'は' mm'が後に使われるなら、未定義の動作を引き起こします。ところで、 'delete mymap [key];'は、 'key'が存在しなければ何も削除しないので、一般的に扱いにくいです。イテレータと一緒に行くのが常に良いです。 @Paulで述べたように、配列の場合は 'delete []'を呼び出す必要があります。 – iammilind

答えて

1

あなたのコードに次のような問題があります。

  1. char*との付き合いあなたがはっきりstd::mapstd::string
  2. を使用するための選択肢を持っている場合、それはあなたがdelete mm[s];に やっているようoperator[]を使用することが常にトリッキーだが、キー= sが存在しない場合、 何も削除しない
  3. で配列を作成するためを使用する場合は、 delete[]を使用する必要があります。それ以外の場合は、未定義の動作です。
  4. 最後にdelete ptr1が危険です。mmを使用した場合は、その後 を使用しているため、ぶら下がったポインタにアクセスしています。

技術的に "未定義の動作"になっているので、Valgrindがメモリリークを表示する理由がわかりません。

私が使用することをお勧めします:

map <string, string> mm; 

または

map <string, std::unique_ptr<char[]>> mm; 
+0

ポイント4:サンプルコードでは、 'mm' *は後で使用されます - デストラクタが呼び出されます。UBを呼び出すのに十分かどうか、またはマップ内の無効なポインタがマップデストラクタに決して触れられていないかどうかを判断するには、かなり慎重な言語弁護士を行う必要があります。 –

+0

@MartinBonner、私はポインタ上のデストラクタを呼び出すとNOp(No Operation)になると思うので、それでも問題ないはずです。上記のケースでは、明らかにそれは使用されていないので、それでもOKです。しかし、実際のコードでは、そのような削除は起こらず、それが起こった場合、対応するマップ要素も消去する必要があります。 – iammilind

+1

ポイント2:「何も削除しない」に間違いはありません。それは試みられているが、バグを示すかもしれない。 – Galik

関連する問題