昨日、この質問コーナーでDirectXとC++を使って、文字を出力すること
について質問させていただきました。的確なアドバイスにより、昨日の
問題は解決したのですが、新たな問題が発生しました。
ちょっと汚いプログラムですが、
for(int i=0; i< strlen(Text); i++)
{
if(IsKanji1st(Text[i])){
NovelChara* Chara=new NovelChara();
Chara->CreateChara(&Text[i], size, size, FontName);
CharaList.push_back(Chara);
i++;
}else{
NovelChara* Chara= new NovelChara();
Chara->CreateChara(&Text[i],size,size, FontName);
CharaList.push_back(Chara);
}
}
のプログラムなんですが、汚いプログラムなんで説明を加えますと、
まず、文字を一文字ずつ作成して格納していくプログラムなのですが、
NovelCharaクラスは一文字のテクスチャ情報を格納するクラス。
それを作って、CreateCharaメソッドを使ってAPIを利用して一文字
の文字画像を作成。それを、CharaListというvectorコンテナに格納
するプログラムです。vector<NovelChara* > CharaList
という感じです。これを使い、文章文字を作成していたのですが、
マップ間を移動するたびにマップ内にいるキャラクターの会話文の生成
と前のマップで作った会話文の破棄を繰り返していたのですが、3往復
マップ間を移動したところで、エラーがでました。
デバッグで確認してみると、vector<NovelChara*> に文字を格納している途中で、

for integer overflow
if (_Count <= 0)
_Count = 0;
else if (((_SIZT)(-1) / _Count) < sizeof (_Ty))
_THROW_NCEE(std::bad_alloc, NULL);

// allocate storage for _Count elements of type _Ty
return ((_Ty _FARQ *)::operator new(_Count * sizeof (_Ty)));
}

のreturn のところで、ブレークポイントが発生しましたとなって、
とまってしまいます。vector内部は全くわからないので、どなたか
このエラーが何が原因で発生しているものなのか知っている方がいらっしゃればアドバイスをお願いしたいのですが

このQ&Aに関連する最新のQ&A

A 回答 (4件)

CharaListを使い終わって開放している部分を確認して下さい。



何もしないで「いきなし、CharaListをdelete」したりすると、確実にメモリリークします。

確実に言える事は1つだけ。それは「newが実行される回数と、deleteが実行される回数は、同じでなければならない」と言う事。

この「回数」には「コピーコンストラクタによる暗黙的なnew」や「auto変数の破棄による暗黙的なdelete」も含まれます。

質問文にあるforループで、auto変数として宣言されている
NovelChara* Chara=new NovelChara();
でnewした「クラスの実体」について「誰がどこでdeleteしてくれているのか」を良く考えて下さい。

少なくとも、CharaListをdeleteする前に、以下の処理が必要です。

1.
CharaList.push_back(Chara);
でプッシュされた回数分、
NovelChara* Chara=new NovelChara();
でnewしたCharaをdeleteする処理。

2.
Chara->CreateChara()
の中で確保された、すべてのオブジェクトを開放する処理(newした物、画像データを格納しているメモリや、画像ハンドラなど)

以下、蛇足。

for(int i=0; i< strlen(Text); i++)
{
if(IsKanji1st(Text[i])){
NovelChara* Chara=new NovelChara();
Chara->CreateChara(&Text[i], size, size, FontName);
CharaList.push_back(Chara);
i++;
}else{
NovelChara* Chara= new NovelChara();
Chara->CreateChara(&Text[i],size,size, FontName);
CharaList.push_back(Chara);
}
}
は無駄。

2バイト文字と1バイト文字の処理は「やる事は一緒」で「やった後にiを2バイト分進めるか、1バイト分進めるかが違うだけ」なので、以下のようにすれば良い。

for(int i=0; i< strlen(Text); i++)
{
NovelChara* Chara=new NovelChara();
Chara->CreateChara(&Text[i], size, size, FontName);
CharaList.push_back(Chara);
if(IsKanji1st(Text[i])) i++;
}

更に言えば、ループで毎回strlen()なんか呼んだら遅いし、ループ内で毎回Text[i]のアドレスを求めるのも無駄だし、Text[i]の中身を取り出す為に、もう一度Text[i]のアドレスを求め直すのも無駄。

こういう時は以下のように「ポインタを有効活用」しよう。

for(char *p = Text; *p; p++)
{
NovelChara* Chara=new NovelChara();
Chara->CreateChara(p, size, size, FontName);
CharaList.push_back(Chara);
if(IsKanji1st(*p)) p++;
}

それと「1文字づつ画像を作る事」そのものが無駄。

API関数には「指定のフォント、指定のサイズで、指定の文字列を描画するには、何×何ピクセルの画像領域が必要かを求める関数」や「指定のフォント、指定のサイズで、指定した文字を画像領域に描画する関数」がある。

それを使えば「1枚の画像に、1行分の文字列が描画された物」を作る事も出来るし、工夫すれば「1枚の画像に、複数行の文字列が描画された物」も作れる。

「1文字づつ、バラバラに1つの画像(テクスチャ)を作る」のはかなり無駄、と言うか、リソースを食いまくるので、何とかした方が…。
    • good
    • 0
この回答へのお礼

非常に参考になりました。
本当にありがとうございます。まずは、メモリーリークの発見を最優先
したいと思いますが、もう一度文字描画クラスを考え直してみます。

お礼日時:2009/05/12 16:35

残念ながらコードの断片しか見えないので, 「確実に解放してるね」とは素直に納得できなかったりします.


そのコード片を実行しているのは確実でしょうか?
NovelBoxChara と NovelChara の関係は?
などなど, 「実は見えないところに問題があるのではないだろうか」と考えられるんですね.

この回答への補足

お騒がせしました。無事解決いたしました。
理由は単純で、デバッグしたときに
_CrtSetBreakAlloc(567);
をコメントにし忘れて、強制的にブレークポイントが
発生するという過ちでした。非常に情けない限りです。

補足日時:2009/05/13 22:37
    • good
    • 0
この回答へのお礼

NovelCharaは一文字のテクスチャ画像に関するクラスで
開放が必要なものはLPDIRECT3DTEXTURE9 Textureのみで、
デストラクタでSAFE_RELEASE(Texture);
と開放しております。

そして、NovelBoxCharaクラスは文字列にして出力管理するクラスです。 ここには vector<NovelChara* > CharaListとして定義してあり
このクラスで開放が必要なのはこの部分のみで、
デストラクタで、
vector<NovelChara*>::iterator it;
for(it=CharaList.begin(); it!=CharaList.end(); it++)
{SAFE_DELETE(*it);}
CharaList.clear();で開放しております。

さらにこのNovelBoxCharaクラスをConversationクラスというが
使っております。
このクラスはmap<string, NovelBoxChara*> Conv;
というmapを持っております。このクラスは他にも解放するもの
があるのですが、引っかかるのはこれのみかな。
このクラスもデストラクタで
map<string, NovelBoxChara*>::iterator it;
for(it= Conv.begin(); it!=Conv.end(); it++){
SAFE_DELETE(it->second);
}
Conv.clear();
とかいほうしております。

このConversationクラスを使ってキャラクタの固有の会話文を
制御していたのですが…。ちょっと使い物にならないので、
もう一度考え直してみます。

お礼日時:2009/05/12 23:16

うん, 私もメモリーリークかなって気がします.


std::vector にポインタを入れた場合, デストラクタで「中のポインタが指しているオブジェクトも delete してくれる」というわけではないです.
    • good
    • 0
この回答へのお礼

う~ん、実は僕もメモリーリークしかないと思っているのです。
なぜなら、例えばマップ間で生成する文字を10文字とした場合には
10往復目ぐらいでシステムダウンするのですが、
変更して生成文字を25に変えると3往復目辺りでシステムダウン
します。といううことは、メモリーリークによりヒープが圧迫
されているということになると僕も考えてはいて、ずっと調べて
いるのです。
でも、開放は、
map<string,NovelBoxChara*>::iterator it;
for(it= LetterBox.begin(); it!=LetterBox.end();it++){
SAFE_DELETE( it->second);
}
LetterBox.clear();
という風にしっかりしていますし、
NovelBoxCharaクラスの解放も見る限りできていて、
デバッグで、
#ifndef _DENUG_H_
#define _DEBUG_H_

#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>

#ifdef _DEBUG
#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
#endif

#endif
を使っても開放漏れに引っかからないとはどういうことか
行き詰っています。メモリーリークの見つけ方でいい方法はないでしょうか。

お礼日時:2009/05/12 15:10

メモリーリークじゃないのでしょうか?

    • good
    • 0
この回答へのお礼

やはり。ショック。
でも、三日探し続けて三千里‥。
面白いこともいえなくなって来ました。

お礼日時:2009/05/12 15:52

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


人気Q&Aランキング