メモリーを解放する方法

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
たかお
記事: 10
登録日時: 11年前

メモリーを解放する方法

#1

投稿記事 by たかお » 11年前

こんにちは。
現在わたしはC+DXライブラリとVisual Studio Express 2012でRPGを製作しています。
配列の要素数を動的に変更したいと考え、malloc関数を使っているのですが、確保したアドレスを解放するときにエラーがでます。

コード:

GameScene GameTest(){

	int items[2] = {3,4};
	int itemSu   = 2;
	char** itemName = (char**)malloc((sizeof (char)) * (itemSu+1));
	Item_GetItemName(items,itemSu,itemName);
	

	//Chara_DrawInfo(items);

	if(itemSu > 0){
		free(items);
		free(itemName);
	}
	
	return GAME_TEST;
}

コード:

void Item_GetItemName(int id[],int kazu,char* itemName[]){
	//kazu分だけchar型配列を生成

	for(int i=0; i<kazu; i++){
		itemName[i] = item_box[id[i]].name;
	}
	itemName[kazu] = NULL;
}

dbgheap.c
ここで「ブレークポイントが発生した」というエラーがでる。

コード:

extern "C" _CRTIMP int __cdecl _CrtIsValidHeapPointer(
        const void * pUserData
        )
{
        if (!pUserData)
            return FALSE;

        if (!_CrtIsValidPointer(pHdr(pUserData), sizeof(_CrtMemBlockHeader), FALSE))
            return FALSE;

        return HeapValidate( _crtheap, 0, pHdr(pUserData) );
}
何が問題なのでしょうか?教えていただきたいです。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: メモリーを解放する方法

#2

投稿記事 by softya(ソフト屋) » 11年前

配列化されたポインタの解放ですので、ちゃんとmallocした数だけforループで回しながら解放しないとダメですね。
あとitemsはmallocしていないのでfreeしないでください。
free( itemName ); ← 先にこちらを解放
free( itemName ); ← こちらは後で。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

box
記事: 2002
登録日時: 14年前

Re: メモリーを解放する方法

#3

投稿記事 by box » 11年前

たかお さんが書きました:

コード:

	char** itemName = (char**)malloc((sizeof (char)) * (itemSu+1));
私が知っている限りにおいて、
malloc()の戻り値を
char **
にキャストするのであれば、
malloc()の引数の型は
char *
つまり、キャストしたい型よりも「1段だけ」低いレベル
でなければならないと思うのですが、いかがでしょうか。
よって、私が知っている限りにおいて、上のコードは

コード:

    char** itemName = (char**)malloc((sizeof (char*)) * (itemSu+1));
または

コード:

    char* itemName = (char*)malloc((sizeof (char)) * (itemSu+1));
のどちらかになるような気がします。いかがでしょうか。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

たかお
記事: 10
登録日時: 11年前

Re: メモリーを解放する方法

#4

投稿記事 by たかお » 11年前

softyaさん、boxさん回答ありがとうございます!

最終的に itemName[itemSu + 1] = {"アイテム名1","アイテム名2",NULL}; このような形にしたいので、

コード:

char** itemName = (char**)malloc((sizeof (char*)) * (itemSu+1));
こちらの書き方にするべきですね。ありがとうございました。

しかし、mallocした数だけ解放しなければならない。ということは理解したのですが、疑問が生まれました。
私は、http://d.hatena.ne.jp/tondol/20090713/1247426321 のサイトを参考にしているのですが、
このサイトの「各行のデータを保持する配列を連続した領域で確保」では、配列を生成しているにも関わらず
一度だけしかメモリを解放していません。他のやり方と何が違うのでしょうか。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: メモリーを解放する方法

#5

投稿記事 by みけCAT » 11年前

softya(ソフト屋) さんが書きました:配列化されたポインタの解放ですので、ちゃんとmallocした数だけforループで回しながら解放しないとダメですね。
あとitemsはmallocしていないのでfreeしないでください。
free( itemName ); ← 先にこちらを解放
free( itemName ); ← こちらは後で。

今回のコードでは、itemNameをfreeする必要はないと思いますが、違いますでしょうか?

item_box.nameをfreeする必要があるのでしたら、そのように書かないと、
二重にfreeしたり、freeする必要があるものをfreeしなかったりする事故の原因になると思います。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: メモリーを解放する方法

#6

投稿記事 by softya(ソフト屋) » 11年前

失礼しました。
char**から早とちりしてchar*もmallocしていると思い込んだようです。
やりたいことからすると必要そうではありますが、現在は行われていない様ですね。
ということで必要な文字列の長さを確保してのmallocも必要です。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

たかお
記事: 10
登録日時: 11年前

Re: メモリーを解放する方法

#7

投稿記事 by たかお » 11年前

先ほど指摘された書き方

コード:

char** itemName = (char**)malloc((sizeof (char*)) * (itemSu+1));
にしたところ、期待通りの結果がでました。

みなさん回答ありがとうございました。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: メモリーを解放する方法

#8

投稿記事 by softya(ソフト屋) » 11年前

あれ? 文字列のポインタをコピーしているだけでしたか。
それなら、free( itemName ); だけでOKです。
忙しい合間に書き込むとダメですね。すいません。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

閉鎖

“C言語何でも質問掲示板” へ戻る