#pragma twice

KAB-studio > プログラミング > #pragma twice > 209 Version 11.09 メモリを動的に確保する

#pragma twice 209 Version 11.09 メモリを動的に確保する

前のページへ 表紙・目次へ 次のページへ

 Version 11.09
メモリを動的に確保する

前回見たように、 CString は文字列の長さに関係なく格納することがで
きます
つまり、配列だとサイズが固定だけど、そうじゃない方法で可変にしてそ
んなかに入れてるわけよね
そういうこと。これを【メモリの動的確保】って言います
動的?
実行中にってこと。普通の変数はサイズが変わらないから、プログラムを
コンパイルした時点でもう決まってるから
それは動的じゃないわけね
というわけで、まずは試してみます。方法はいくつかあるんだけど、今回
はランタイムを使います

void AllocAndFree()
{
    // このデータが入る領域を確保します。
    const char *const DATA = "あいうえお";

    // まず確保。
    char *pch = (char *)malloc( strlen( DATA ) + 1 );

    // コピーしてから出力。
    strcpy( pch, DATA );
    TRACE( "%s\n", pch );

    // 解放します。
    free( pch );
}

初めて見るのばっかって感じ
まず、このプログラムは

    const char *const DATA = "あいうえお";

が入る領域をメモリに確保して、その中にコピー、それを出力、ってする
プログラムです
つまりこの文字列がどんなに長くても問題ないってことね
そういうこと。そこで、まずこの文字列が入る領域を確保します

    // まず確保。
    char *pch = (char *)malloc( strlen( DATA ) + 1 );

 malloc() がそのランタイム?
そう。 malloc() は、引数で渡されたバイト数だけ、メモリを確保しま

その、メモリを確保するって……
まずメモリウィンドウを想像して
ほい想像した
その中は、変数として使われてるところもあれば、使われてないところも
あります
だね
雰囲気としては、野球場の指定席
へ?
野球場の観覧席、その指定席がメモリ。もう場所が取られてるところもあ
れば、まだ空いてるところもあります
うん
メモリを確保するってことは、ぴあとかに頼んで席を予約すること
ああ! そういう意味の確保なんだ
引数として渡した数字が、その確保した大きさ、つまり席の数ってことに
なります
戻り値は?
戻り値はポインタ。予約した席が並んでたら、その並びの最初の席番号っ
てことになるかな
最初の……って、配列のポインタみたいだね
というかそのまま。 Version 5.03 ( No.068 ) でも教えたように、ポイ
ンタはそのまま配列としても使えるわけだから
ってことは

    char *pch = (char *)malloc( strlen( DATA ) + 1 );



    char pch[ strlen( DATA ) + 1 ];

って考えちゃえばいいんだ
まぁそういうこと。だから

    // コピーしてから出力。
    strcpy( pch, DATA );
    TRACE( "%s\n", pch );

っていうふうに、普通に使えます
これはいつも通りね
配列と違うのは、確保したら解放しなきゃいけないってこと

    // 解放します。
    free( pch );

予約しっぱなしじゃダメってこと?
そういうこと。当たり前だけど、 malloc() で確保した領域と同じ領域を
malloc() が返すことはないでしょ

たとえば10バイト malloc() に頼んで 0x00000001 ってアドレスが返っ
てきたとします。そうしたら、もう一度呼んだときに malloc() が 
0x00000001 を返す事はないってこと
返されたら……他で使ってるとこに上書きとかしちゃうものね
それに、確保した領域の範囲ももちろん返しません。 0x00000005 とかも
返らないってこと
ってゆーか、それはさっきの野球の席の話でもそうよね。ダブルブッキン
グになるんだから
ってことは、 free() で〈もう使いません〉って言うまでは、 
0x00000001 - 0x00000010 は malloc() が返さないから使えない、ってこ

? だって、最初にもらってあるんだからそれ使えばいいんじゃない
そのポインタをちゃんと取ってあるんなら、ってこと

void AllocNotFree()
{
    // このデータが入る領域を確保します。
    const char *const DATA = "あいうえお";

    // まず確保。
    char *pch = (char *)malloc( strlen( DATA ) + 1 );

    // コピーしてから出力。
    strcpy( pch, DATA );
    TRACE( "%s\n", pch );

    // 解放……しません。
    // free( pch );
}

っていうように、もし free() し忘れたら、 pch の中のアドレスはもう
どうやってもわからないから
使うこともできないし、 free() もできない……
この、メモリ領域が無駄になることを【メモリリーク】って言います
リーク?
英語で leak 、〈漏れる〉って意味。メモリが漏れてなくなるって意味か
な、ちょっとわかりづらいけど
なんか英語的かも……
で、実際にメモリリークが影響する部分だけど、大きい場合もあれば小さ
い場合もあります
そなの?
まず、 Version 8.04 ( No.146 ) で言ったように、メモリ領域はプロセ
スごとに違うから、 malloc() しっぱなしのアドレスが確保できない、って
のは自分のプログラムだけの話
そっか、このプログラムが 0x00000001 を確保してメモリリークしちゃっ
ても、他は関係ないから 0x00000001 を確保できたりするんだ
ただ、物理的なメモリは取っちゃうわけだから
げ、メモリリークしまくったらメモリが無駄に消費されちゃう
そういうこと。でも、実は malloc() した領域は、アプリが終了すると全
部解放されるんです
へ? 確保しっぱなしじゃないの?
しっぱなしじゃないんです。だから終了しちゃえばリセット
なんだ、問題ないんじゃない
っていうのは間違い
え”
プログラムをどう使うかはユーザー次第。ダイアログアプリで、1年間終
了せずに使いっぱなしにされることだってあるんだから
そっか、それを1分で終了させるか1年間終了させないか、なんてわかん
ないもんね……
昔は実行したらすぐ終わるプログラムが多い事もあって〈解放しなくても
いい〉って風潮があったんだけど、今はウィンドウプログラムだから
いつ終わるかわからない、だからメモリリークはちゃんとチェックしない
とダメ
ってことになります。で、チェックの方法について。さっきのプログラム
を実行して終了すると、こんなメッセージが出ると思います

Detected memory leaks!
Dumping objects ->
{69} normal block at 0x004215A0, 11 bytes long.
 Data: <           > 82 A0 82 A2 82 A4 82 A6 82 A8 00 
Object dump complete.

うん、出てる。あ! 〈 memory leaks 〉って出てる!
そう、メモリリークするとそれを自動的に検出してくれるんです。 
malloc() で確保したポインタは中で取ってあって、アプリが終了する時に解
放し忘れてるポインタがないかチェックしてくれるから
こういうふうにわかるわけね
ただ、このメッセージそのものはちょっとわかりにくいかな。見方は、ま


{69} normal block at 0x004215A0, 11 bytes long.

この行だけど、 69 はポインタの番号みたいなので、中の話だから特に
気にしなくていいです。 0x004215A0 はメモリリークしたアドレス、つまり
malloc() で返ってきたアドレス
じゃあ malloc() したアドレス全部出力すれば
まぁ一応はわかるけど、ちょっと大変だね……。 11 は malloc() で確保
したサイズ。で、次

 Data: <           > 82 A0 82 A2 82 A4 82 A6 82 A8 00 

この <> の中は、実際にそのポインタに入ってるデータを文字列化したも
の、その右側の 82 A0 とかは1バイトずつ16進数で表記したもの
文字列化したの、空欄だから全然わかんないんだけど
日本語が出力できないからこうなっちゃってるんだよね。それよりは右の
16進表記を見た方がいいかも
そっちだってわかんないし
わかんない?
へ?
前に見たことあると思うけど
うーん……
 Version 11.05 ( No.205 ) でやったでしょ、 "あ" の文字コードは?
 0x82 0xA0 ……あ!!
というわけ。だいたいこれで中身がわかるから、それもヒントになるか


/*
    Preview Next Story!
*/
わけわかんないこと書いてあるっぽくても、わかるもんなのね
ちゃんとわかれば、難しいことなんて本当に少ないよ
うー、なんか説得力ない
そんなことないって。次の話も結局はペアになるっていう話
ペア?
というわけで次回
< Version 11.10 いろいろあるメモリ確保の方法 >
につづく!
プログラムは〈作った〉ものなんだから、基本は単純なんだって
ホントかなー
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。