libc の malloc がいったいどこにメモリ確保をするのか?
以下は Cygwin で GCC な話として。まとまってないし結論無いけど。ちょっと詰まったのでメモとして書いておく。
- その1
まず下記のコード。
#include <stdio.h> #include <stdlib.h> #include <string.h> void test(char *p) { char *str; str = malloc(sizeof(char) * (strlen("foo") + 1)); strcpy(str, "foo"); printf("0x%08x %s\n", p, (int)p); printf("0x%08x %s\n", str, (int)str); free(str); } int main(int argc, char *argv[]) { char *tmp, *tmp2; tmp = malloc(13); strcpy(tmp, "hoge"); test(tmp); tmp2 = malloc(10); strcpy(tmp2, "fuga"); test(tmp2); free(tmp); free(tmp2); return 0; }
出力結果。
isshiki1@isshiki ~/test/memtest
$ ./a
0x00660180 hoge
0x00660198 foo
0x00660198 fuga
0x006701b0 foo
下記に注目。
0x00660180 hoge 0x00660198 fuga
「0x18」バイトほどの offset の位置に確保された。2回目の「foo」が離れた位置に確保されている。
- その2
んで下記のコード。
#include <stdio.h> #include <stdlib.h> #include <string.h> void test(char *p) { char *str; str = malloc(sizeof(char) * (strlen("foo") + 1)); strcpy(str, "foo"); printf("0x%08x %s\n", p, (int)p); printf("0x%08x %s\n", str, (int)str); free(str); } int main(int argc, char *argv[]) { char *tmp, *tmp2; tmp = malloc(8); strcpy(tmp, "hoge"); test(tmp); tmp2 = malloc(13); strcpy(tmp2, "fuga"); test(tmp2); free(tmp); free(tmp2); return 0; }
出力結果。
isshiki1@isshiki ~/test/memtest
$ ./a.exe
0x00660180 hoge
0x00660190 foo
0x006701a8 fuga
0x00660190 foo
0x00660180 hoge 0x006701a8 fuga
えらく遠くの場所に確保された。「その1」の「foo」に近い位置に確保されている。
ポイントとしては、両方とも tmp、tmp2 がメモリ確保する間に「test()」関数の中でメモリが確保している。
- その3
こうしてみるとどうか?
#include <stdio.h> #include <stdlib.h> #include <string.h> void test(char *p) { char *str; str = malloc(sizeof(char) * (strlen("foo") + 1)); strcpy(str, "foo"); printf("0x%08x %s\n", p, (int)p); printf("0x%08x %s\n", str, (int)str); free(str); } int main(int argc, char *argv[]) { char *tmp, *tmp2; tmp = malloc(13); tmp2 = malloc(10); strcpy(tmp, "hoge"); test(tmp); strcpy(tmp2, "fuga"); test(tmp2); free(tmp); free(tmp2); return 0; }
isshiki1@isshiki ~/test/memtest
$ ./a
0x00660180 hoge
0x006601a8 foo
0x00660198 fuga
0x006601a8 foo
- その4
#include <stdio.h> #include <stdlib.h> #include <string.h> void test(char *p) { char *str; str = malloc(sizeof(char) * (strlen("foo") + 1)); strcpy(str, "foo"); printf("0x%08x %s\n", p, (int)p); printf("0x%08x %s\n", str, (int)str); free(str); } int main(int argc, char *argv[]) { char *tmp, *tmp2; tmp = malloc(8); tmp2 = malloc(13); strcpy(tmp, "hoge"); test(tmp); strcpy(tmp2, "fuga"); test(tmp2); free(tmp); free(tmp2); return 0; }
isshiki1@isshiki ~/test/memtest
$ ./a
0x00660180 hoge
0x006601a8 foo
0x00660190 fuga
0x006601a8 foo
ふむ。
というわけで、疑問点は「その1」「その2」で、突然かけ離れたところに確保されたという事だ。 64K 位離れてる。
全く訳のわからない値ではないので(<64K くらいという値自体)何か意味がありそうだが。メモリページのバウンダリ(<?)にまたがってしまったため確保アドレスがそうなってしまった、とか言う話なのかなあ?