Welcome to FutureAppLaboratory

v=(*^ワ^*)=v

checkstack.plを遊んでみた

| Comments

偶には再帰メソッドの消費メモリーが気になるので、

どうやって調べるのを調べたら、Linux OSに付いているcheckstack.plを見つけた。

ソースをgistに上げました。checkstack.pl

ちなみに、154行目のnext if ($size < 100);をコメントアウト済み。

そうすれば、スタックサイズが100以下のメソッドもリストアップしてくれた。

テスト用のソース

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
using namespace std;

struct Point {
    float px;
    float py;
    Point(float _x, float _y):px(_x),py(_y) {}
};

int func() {
    int i = 4;
    int j = 4;
    return i + j;
}

void func_arr_int_1() {
    int arr[1];
    arr[0] = 0xFFFFFFFF;
}

void func_arr_int_2() {
    int arr[2];
}

void func_arr_int_3() {
    int arr[3];
}

void func_arr_int_4() {
    int arr[4];
}

void func_point() {
    Point p = Point(0.0f, 0.0f);
}

int main(int argc, char* argv[]) {
    func();
    func_arr_int_1();
    func_arr_int_2();
    func_arr_int_3();
    func_arr_int_4();
    func_point();
    return 0;
}

使う

macなのでobjdumpではなくgobjdumpを使う。homebrewでインストールすると便利

g++ stack_test.cpp
gobjdump -d a.out | checkstack

結果

0x000100000e14 __Z14func_arr_int_2v []:   16
0x000100000e33 __Z14func_arr_int_2v []:   16
0x000100000e44 __Z14func_arr_int_3v []:   32
0x000100000e63 __Z14func_arr_int_3v []:   32
0x000100000e74 __Z14func_arr_int_4v []:   32
0x000100000e93 __Z14func_arr_int_4v []:   32
0x000100000ea4 __Z10func_pointv []:   16
0x000100000ebe __Z10func_pointv []:   16
0x000100000ed4 _main []:    32
0x000100000f09 _main []:    32
0x000100000f14 __ZN5PointC1Eff []:   16
0x000100000f39 __ZN5PointC1Eff []:   16

今のコンパイラって結構やってくれるな。

func1ではレジストで操作したからスタック消費はなし。

func_arr_int_1がスタック消費がないのは驚いた。size = 1のarrayは最適化されてなくなったみたい。

x64マシンなので、メモリー最小単位は16byteになるのか?

func_arr_int_2は16byte。func_arr_int_3は実際24byteだと思うが、スタックサイズは32byteになった。メモリーは2単位取ったね。

checkstack.plの原理

 elsif ($arch =~ /^x86(_64)?$/ || $arch =~ /^i[3456]86$/) {
    #c0105234:       81 ec ac 05 00 00       sub    $0x5ac,%esp
    # or
    #    2f60:    48 81 ec e8 05 00 00       sub    $0x5e8,%rsp
    $re = qr/^.*[as][du][db]    \$(0x$x{1,8}),\%(e|r)sp$/o;
    $dre = qr/^.*[as][du][db]    (%.*),\%(e|r)sp$/o;
}

逆コンパイルされたコードの中のadd, sub, esp, rspを探して、スタックサイズを計算するらしい。

参考:http://0xcc.net/blog/archives/000115.html

Comments