メモリーリークの調べ方 – プログラミング – Home

メモリーリークの調べ方
 
通知
すべてクリア

[解決済] メモリーリークの調べ方


Puppy
 Puppy
(@Puppy)
ゲスト
結合: 23年前
投稿: 71
Topic starter  

Puppyです。 お世話になっています。
Win2000,VC6.0,MFC,MDIで開発してます。
先日、メモリの確保についていろいろと教わりました。
メモリの確保と解放を

char (* pDat)[5][10] = new char[day][5][10];

// いろいろな操作

delete[] pDat;

としています。
このパターンであちこちの関数に使っているのですが
何回か、ここにくると、そのうちに「メモリが不足しています」というウィンドウが
出てしまいます。
上記の方法で、問題ないでしょうか?
また、メモリーリークをどのように見つけたらよいでしょうか?
よろしくお願いします。 m(..)m ペコリ


引用未解決
トピックタグ
ん
 ん
(@ん)
ゲスト
結合: 23年前
投稿: 81
 

まず、書式があっているかと、new に対して必ず delete が
行われているかという話しがあると思います。

書式の方は、ぱっと見おかしいところは私にはわからないので、
new delete の対応チェックだけ。

> char (* pDat)[5][10] = new char[day][5][10];
> new_cnt++ ;
> sv_pDat = pDat ;
>
> // いろいろな操作
>
> if( sv_pDat != pDat ) ポインタ異常発見 ;
> delete[] pDat;
> new_cnt-- ;

なんか、かっこわるい方法ですが、これでdelete 漏れと
ポインタ変数の値のくらいはチェックできるんではないでしょうか?

まー、ご参考ってことで。


返信引用
dairygoods
 dairygoods
(@dairygoods)
ゲスト
結合: 23年前
投稿: 1421
 

> char (* pDat)[5][10] = new char[day][5][10];
> // いろいろな操作
> delete[] pDat;

こんなのが、いろいろなところにあったら対応を
チェックするのも面倒ですよね。

メモリリークを防ぐには、newやdeleteを使わないのが最善の方法です。
つまり、メモリの確保と開放を勝手にやってくれるSTLやMFCの
コレクションクラスを使うべきです。

CArray<char,char> array;
array.SetSize(day*5*10);
char (* pDat)[5][10] = (char(*)[5][10])array.GetData();

// いろいろな操作

自作するなら、こんな:p)
class Dayx5x10
{
public:
explicit Dayx5x10(int days):p(new char[days][5][10]){}
~Dayx5x10() { delete[] p ; }
char (*operator[](int i))[10] { return p[i]; }
private:
char (*p)[5][10];
Dayx5x10(const Dayx5x10& o); // コピー禁止
Dayx5x10& operator=(const Dayx5x10& o); // 代入禁止
};

Dayx5x10 data(day);
// いろいろな操作


返信引用
第3水準
 第3水準
(@第3水準)
ゲスト
結合: 23年前
投稿: 17
 

メモリリークしてる場所を見つけるだけなら、
Debug実行の終了時にリーク場所がアウトプットウィンドウに表示されます。

こんな感じ

Detected memory leaks!
Dumping objects ->
C:\Work\VCPP\memoryleak\memoryleak.cpp(36) : {57} normal block at 0x003444D8,
100 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.

この場合memoryleak.cppの36行目で確保したメモリが開放されずにメモリリークしてます。


返信引用
Puppy
 Puppy
(@Puppy)
ゲスト
結合: 23年前
投稿: 71
Topic starter  

んさん dairygoodsさん 第3水準さん お返事ありがとうございます。

>CArray<char,char> array;
>array.SetSize(day*5*10);
>char (* pDat)[5][10] = (char(*)[5][10])array.GetData();

このやりかただと pDat[day][5][10] の3次元配列でメモリを確保し
pDat が char * 型になるのでしょうか?
そして解放忘れなどは考えなくっていいんですか?

言い忘れていたんですけどぉ、dayは変数(1-31)です。これも問題なしですか?

>こんなのが、いろいろなところにあったら対応を
>チェックするのも面倒ですよね。

ホントもう、悩んでやんなっちゃいますぅ。(涙)

まず、気持ち悪いのでメモリーリークを見つけてから、
その後で、安全な方法に変更しようと思います。

お返事、お待ちしています。いつもご迷惑をおかけします。 m(..)m ペコリ


返信引用
dairygoods
 dairygoods
(@dairygoods)
ゲスト
結合: 23年前
投稿: 1421
 

> このやりかただと pDat[day][5][10] の3次元配列でメモリを確保し
> pDat が char * 型になるのでしょうか?
> そして解放忘れなどは考えなくっていいんですか?

CArrayは多次元配列を扱えないので、1次元でchar[day][5][10] と
同じサイズのメモリを確保して、3次元配列ポインタにキャストしています。

CArrayは、内部でこっそり配列をnewして保持しており、
変数(array)がスコープ外になったときに、勝手に解放します。
なので、解放忘れを気にする必要はありません。


返信引用
YuO
 YuO
(@YuO)
ゲスト
結合: 24年前
投稿: 252
 

> CArrayは多次元配列を扱えないので

配列の参照は存在しないというC++の制限ですね。
そのあたりはstd::vectorでも同じです。

std::vector<std::vector<std::vector<char> > > array;
のように,最高次以外もコンテナにしてやるのが基本です。
あとは,boostライブラリのboost::shared_arrayとかboost::scoped_arrayを使えば,

typedef char TYPE[5][10];
boost::scoped_array<TYPE> pDat(new TYPE[day]);
という形で確保できます。
#scoped/shared_arrayにはoperator=が無いので,テンポラリを作成して代入になりますが。


返信引用
Puppy
 Puppy
(@Puppy)
ゲスト
結合: 23年前
投稿: 71
Topic starter  

dairygoodsさん お返事ありがとうございます。

不具合の場所が見つかりましたぁ。(^-^;
月のかわりめで day の値と確保する配列のサイズがあっていませんでした。

>CArrayは多次元配列を扱えないので、1次元でchar[day][5][10] と
>同じサイズのメモリを確保して、3次元配列ポインタにキャストしています。

これからCArrayにチャレンジしてみます。

>CArrayは、内部でこっそり配列をnewして保持しており、

ふーむ、ズルいけど、便利なんですね。CArray って。
またわからないことがありましたら、質問しますのでお願いします。m(..)mペコリ

皆様、ありがとうございました。


返信引用
PAI
 PAI
(@PAI)
ゲスト
結合: 23年前
投稿: 359
 

struct DateData{
char m_Data [5][10];
};

std::vector<DateData> a;

じゃだめなん?


返信引用
Puppy
 Puppy
(@Puppy)
ゲスト
結合: 23年前
投稿: 71
Topic starter  

YuOさん PAIさん お返事ありがとうございます。

std::vectorも試してみようと思います。
また、わからなかったら質問させていただきます。

ありがとうございました。m(..)mペコリ


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました