vectorを含んだ構造体のメモリ開放について

[戻る]
ひろぴー 2004/04/19(月) 14:15:03
暫く顔を出していませんでしたが、いきなり質問で申し訳ありません。

ある構造体をA、そのAのvectorをメンバに含む構造体をBとした場合、宣言の違いによりメモリ
リークがおこっており、(自分的に)原因不明の為ご存知の方がいらっしゃいましたらご教示願
えますでしょうか?

// 構造体の宣言

typedef struct _A{
    DWORD test1;
}A, *LPA;

typedef struct _B{
    vector<A> vecA;
}B, *LPB;



1.メモリリークなし

B b;
A a;

for ( int i=0; i<100; i++ )
{
    a.test1 = i;
    b.vecA.push_back( a );
}
     ・
     ・
     ・
b.vecA.clear();


2.メモリリークあり

LPB pB = (LPB)LocalAlloc( LPTR, sizeof( B ) );
A a;

// pB != NULL の場合に以下の処理を行っています

for ( int i=0; i<100; i++ )
{
    a.test1 = i;
    pB->vecA.push_back( a );
}
     ・
     ・
     ・
pB->vecA.clear();
LocalFree( pB );

BoundsCheckerという製品でチェックしたところ、push_back()でnewしたものが開放されてい
ないと怒られます。
製品の不具合なら良いのですが(似たような製品でも抽出できないケースや勘違い(?)がある
為)何か自分が勘違いしていますでしょうか?

環境 : Win2000 SP5   VC++6.0 SP6

n 2004/04/19(月) 14:49:08
pB = new B;
 :
 :
delete pB;

としなければならないのでは。

dairygoods 2004/04/19(月) 15:04:37
2.の場合、Bのコンストラクタが呼ばれないので、
メンバが正しく初期化されません。

どうしてもLocalAllocを使わなければならないなら、placement newを使います。

#include <new>

LPB pB = (LPB)LocalAlloc( LPTR, sizeof( B ) );
new (pB) B;
...

tetrapod 2004/04/19(月) 15:58:07
placement new を使った場合は明示デストラクションも必要ですね。
他でこの構文を使うの見たことないというか。

PATIO 2004/04/19(月) 16:10:07
placement newって実際はそうそう使わざる得ない場面に直面する事はないですよね。

それから考えると今回のケースも単にC++に慣れていなくてnewしなければならない
意味が良く分かっていない事が原因のような気がしますね。
newを使わないとコンストラクタが動作しない事は入門書でも触れられていると
思うのでもう一度C++言語の入門書を読み返される事をお勧めします。
くれぐれもVC++の入門書で済ませてしまいませんように。
VC++の入門書ではC++の勉強になりませんので。

C++の知識が既にあるという話でしたら、Effective C++をお読みになると良いかと
思います。クラスの使い方など実践に即した話がたくさん収録されています。
但し、C++の知識は既にある事が前提で書かれていますので、自信が無い様であれば
入門書の方を確認された方がいいかもしれません。

ひろぴー 2004/04/19(月) 16:52:47
[[解決]]
レスありがとうございます。

nさん

newを使うと確かにうまく行きました。


dairygoodsさん

> どうしてもLocalAllocを使わなければならないなら、placement newを使います。
placement new 初めて知りました(汗)
で、やってみたのですが、メモリリークは依然発生したままでした。


tetrapodさん

> placement new を使った場合は明示デストラクションも必要ですね。
pB->~B;
とする事でメモリリークがなくなりました。


あとはnewを使用する方法、placement newを使用する方法で検討するだけとなりました。
nさん、dairygoodsさん、tetrapodさん、ありがとうございました。



PATIOさん

> それから考えると今回のケースも単にC++に慣れていなくてnewしなければならない
> 意味が良く分かっていない事が原因のような気がしますね。
今回の事でnewの意味を思い出しました(こんな事でいいのか?俺)
いい加減にしてきたツケが来たのだと認識し、精進したいと思います。
ありがとうございました。

ひろぴー 2004/04/19(月) 16:54:23
すみません、

> pB->~B;

ではなく

pB->~B();
でした(ToT)

古いスレッドには追加発言できません。