mallocの動作

ActiveBasicでのプログラミングでわからないこと、困ったことなどがあったら、ここで質問してみましょう(質問を行う場合は、過去ログやWeb上であらかじめ問題を整理するようにしましょう☆)。
返信する
メッセージ
作成者
ゲスト

mallocの動作

#1 投稿記事 by ゲスト »

こんにちは

mallocの引数に指定する値ですが、色々試しているうちに文字数とどうも違うようですね(メモリのサイズ <> 代入する文字の文字数)。
どのような値を指定すればいいのですか?

確保するメモリのサイズ=代入する文字の文字数 だった場合、以下のコードは通らないはずですが、無事に表示されます。

コード: 全て選択

Dim lpBuf As BytePtr
lpBuf = malloc(10)
lstrcpy(lpBuf,"aaaaaaaaaaaaaaaaaaaa")
MessageBox(NULL,lpBuf,NULL,MB_OK)
free(lpBuf)
End
OverTaker
記事: 231
登録日時: 2005年5月31日(火) 17:14
お住まい: 茨城県

#2 投稿記事 by OverTaker »

なかなか良い質問ですね。
確保するメモリのサイズ=代入する文字の文字数 だった場合、以下のコードは通らないはずですが、無事に表示されます。
まずこれについてですが、コンパイルの時点でコンパイラがチェックするのは、文法的におかしいかどうかであり、文法が正しければエラーが出ることはありません。これは当たり前なので理解できると思います。従って、コード的には何も問題がないわけです。
mallocの引数に指定する値ですが、色々試しているうちに文字数とどうも違うようですね(メモリのサイズ <> 代入する文字の文字数)。
どのような値を指定すればいいのですか?
先に答えだけ書くと、文字列が使用する容量分だけ指定します。これは文字コードによって変化しますので、詳しいことは他で調べていただきたいのですが、文字列が使用する容量はLen()やlstrlen()で取得することができます。ただし、文字列の最後には空の文字(NULL=0)を入れるという規則があるので、実際には文字列の容量+1となります。

さて、今回の話の中心であるmalloc()についてですが、これはメモリをバイト単位で確保するものです。ですから、例えば下のコードのようにmalloc(10)とやれば、10バイト分のメモリが確保されることになります。注意すべき点はここからで、変数のBufferに10バイト分のメモリが確保された、ということではない点です。BytePtr型は32bit型で4バイトです。では、malloc()一体何を返しているのかといえば、10バイトのメモリを確保した位置(場所)、すなわちメモリのアドレスを返しています。このアドレスが32bitになっているために、BytePtr型を使用するわけです。ちなみに、Bufferのような変数のことをポインタ(pointer)というのは、メモリの位置を指し示すもの(point + er = pointer)、というところから来ていると思います。

コード: 全て選択

Dim Buffer As BytePtr 
Buffer = malloc(10) 
lstrcpy(Buffer,"aaaaaaaaaaaaaaaaaaaa") 
問題のlstrcpy()ですが、これは絶対にしてはいけないもののうちの一つとして数えても良い物です。lstrcpy()は、Bufferが示すアドレスの位置に文字列をコピーするものですが、確保したメモリは10バイトです。こうすると一体どんなことが起こるかというと、確保した10バイトのメモリ以外の、関係のないメモリ空間まで文字列がコピーされることになります。

例えば、malloc(10)で確保したメモリ空間のアドレスが、101番地から110番地だったとします。そしてポインタであるBufferには、確保したメモリの先頭のアドレスである101番地が入ります。ポインタには、確保したメモリの先頭のアドレスを代入する決まりがあるので101番地です。そしてlstrcpy()では、Bufferのアドレス、すなわち101番地のところへ文字列がコピーされていくわけですが、先頭から順にメモリ空間へコピーされていきます。つまり、10バイト分の文字列ならば無事に101番から110番までの、mallocで確保した分だけのメモリ空間にコピーされますが、もしそれ以上の文字列をコピーした場合、確保していない110番目以降のところにも文字列がコピーされてしまうことになります。例えば、20バイトの文字列をコピーした場合、101番地から120番地まで使ってしまうというような感じです。

もしこうなると大変です。110番目以降のメモリは誰が使っているのかわかりません。もし他のアプリケーションが使用していたなんてことになると、どういうことになるかは簡単に想像が着くでしょう。


相変わらず長文になってしまったのは私の反省すべき点ですが、理解することができたでしょうか?理解できたのなら、一番最初にあげた質問の答えも納得がいくようになると思います。
ゲスト

#3 投稿記事 by ゲスト »

こんにちは

メモリに関してある程度は知っているつもりでしたが、全然分かってないみたいですね・・・
もっと勉強してみます。

OverTakerさん、回答さらには丁寧に解説までしていただきありがとうございました。
返信する