今日の雑記

生きることでいっぱいいっぱい

libc の malloc がいったいどこにメモリ確保をするのか?

以下は CygwinGCC な話として。まとまってないし結論無いけど。ちょっと詰まったのでメモとして書いておく。

  • その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 くらいという値自体)何か意味がありそうだが。メモリページのバウンダリ(<?)にまたがってしまったため確保アドレスがそうなってしまった、とか言う話なのかなあ?