2012-04-28 26 views
3

私はvalgrindの初心者ですので、何か間違っているかもしれませんが、valgrindがallocsより多くの解放を報告したらどうしたらいいですか? valgrindはallocsより多くの解放を報告します

はここSSCCEガット:罰金コンパイルして、あまりにも罰金を実行しますが、valgrindのは

==15925== Invalid free()/delete/delete[] 
==15925== at 0x40221EA: operator delete[](void*) (vg_replace_malloc.c:364) 
==15925== by 0x8048689: something::~something() (test.cpp:12) 
==15925== by 0x80485F5: main (test.cpp:19) 
==15925== Address 0x42b7028 is 0 bytes inside a block of size 4 free'd 
==15925== at 0x40221EA: operator delete[](void*) (vg_replace_malloc.c:364) 
==15925== by 0x8048689: something::~something() (test.cpp:12) 
==15925== by 0x80485E5: main (test.cpp:18) 
==15925== 
==15925== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 18 from 1) 
==15925== malloc/free: in use at exit: 0 bytes in 0 blocks. 
==15925== malloc/free: 1 allocs, 2 frees, 4 bytes allocated. 
==15925== For counts of detected errors, rerun with: -v 
==15925== All heap blocks were freed -- no leaks are possible. 

言うと、私はなぜわからないんだ

#include <cstring> 

class something 
{ 
protected: 
    char* ptr; 
public: 
    something() {ptr = NULL;} 
    something(const char* value) { 
     ptr = new char[strlen(value)+1]; strcpy(ptr, value); 
    } 
    ~something() {delete[] ptr; ptr = NULL;} 
}; 

int main() 
{ 
    something x; 
    x = "123"; 
    return 0; 
} 


もちろん、私は教育的な推測をすることができます - 明らかに違反行は、それがx = "123";と言う場所であり、あなたがそれをコメントすれば、すべてが良いです。しかし、なぜコンパイラは-Wall -Wextra -pedanticを使っても、これが問題ないと思いますか?私はこのプログラムに問題があることを伝えるコンパイラスイッチを忘れてしまったのでしょうか?

答えて

1

Rule of threeを実装するのを忘れました。
コピーコンストラクタとコピー代入演算子を指定する必要があります。

x = "123"; 

オブジェクトの簡易コピーを作成し、暗黙的に生成されたコピー代入演算子を呼び出して、一時的に破壊されます一度デストラクタはダングリングポインタとしてポインタのメンバーを残して割り当てられたメモリの割り当てを解除します。

+0

間違いなく。しかし、私の最終的な質問は残っています。これらの種類のものを検出できる 'g ++ 'へのコンパイラスイッチがありますか? –

+0

@MrLister:残念ながら、Rule of ThreeはC++標準の一部ではありません(理想的にはそうだったはずです)ので、コンパイラは違反していると不平を言うことはありません.AFAIKも、それについて報告するコンパイラの拡張はありません。 –

1

x = "123"は、暗黙のコピー代入演算子を呼び出すx = something("123")に相当します。一時的なsomethingは破壊されますが、xであり、どちらもdelete []の同じ生ポインタです。

解決策は、Rule of Threeに従うか、スマートポインタ/コンテナを使用してメモリ管理を行うことです。

0

somethingクラスには、(コンパイラ提供の)コピーコンストラクタと代入演算子で適切に管理されていないローポインタが含まれています。生ポインタを使用しないでください。必要がある場合は、クラスメソッドをより慎重に定義してください。しかし実際には、生ポインタを使用しないでください。

+0

生ポインタを恐れてはいけません。あなたの 'new'sがあなたの' delete'sに合っていることを確認する限り、つまり、あなたがポインタへのアクセスを制御するプロセス以外のプロセスを許可しないようにします。私の例では、コンストラクタだけが 'new'を行うことができ、デストラクタだけが' delete'を実行できます。 –

+0

あなたがスマートなポインタを使っていたなら、決して起こったことのない問題があったので、あなたはここに来た人です。オブジェクトのライフタイムを管理しているときに、今日の生ポインタを使用する理由はほとんどありません。さまざまなライブラリやさまざまなライブラリで利用可能なもの、そして最近では標準C++でも使用できます。今あなたが言うのは、あなたが自分を正しく使用しなかったときに生ポインタを使用するのを恐れてはいけないということです。わかりません。 –

+0

ああ、申し訳ありませんが私は怒った場合。たぶんそれは私の代わりにC#への露出を強制する反動で、言語があなたの手を保持し、あなたが傷つける可能性があると思うことは何もしません。私はこれのような間違いからはるかに多くを学ぶのに対して。もう一度、申し訳ありません。 –

関連する問題