C/C++はメモリ管理ができないとお話にならないわけですが、にも関わらずC系の入門書では「ポインタ?簡単だよ、ほら、この図を見て」なんて感じにお茶を濁してる。うーんこの。抽象的に説明しちゃうから抽象的な理解しかできないわけです、かく言う私がそうです。
それはともかく、Cを書いていて若干ハマったのでメモっておく。私のようなC初学者ですと、ソースが構造体だらけになってしまい、「困ったら構造体にぶち込んじゃえ」みたいなアレになります。そんな構造体のお話。
例えばこんなコードがあって、構造体のメモリを動的に確保し、さらにその内部の変数も動的に確保したいなぁとか考えたとします。
#include <stdio.h> #include <stdlib.h> #include <string.h> #define NUMS 4 typedef struct T_FOOBAR { int foo; char *bar; } FOOBAR; int main() { FOOBAR *foobar; foobar = (FOOBAR*)malloc(sizeof(FOOBAR)); foobar->bar = (char*)malloc(NUMS*sizeof(char)); (以下略)
こんなことやっちゃってました、愚かですよね。
というのも、この後にmemcpyでFOOBAR構造体の先頭アドレスに指定サイズ分の値をコピーしようとしていたのですが、うまく入らないわけ。なぜかというと、mallocで動的確保した番地は、foobarとfoobar->barで全く異なるからです。
malloc直後に、printfで番地を表示させるとこうなりました。
foobar : 0x00488D50 foobar->bar : 0x00488d98
ぜんぜん違うやんこれ。なので、0x00488D50から例えば12バイト分、値をコピーしちゃうと、foo以降にはゴミが乗っかちゃって、barに入るべき値はメモリの彼方へ消えているというわけ(消えてないけど、すぐ後ろにいるけど)。
解決策としては、バッファ変数を用意してからのいろいろやればいいってだけ。もしくは、そもそも構造体である必要が無いのであれば使わない、とか。