いっしょにtalk C栗(第百三十回:C言語例--Cプログラムメモリレイアウト二)
25241 ワード
皆さん、こんにちは、前回はCプログラムのメモリレイアウトの例を話しましたが、今回はこの例を続けてみましょう.余談はさておき,話は本筋に戻る.一緒にtalk C栗を食べましょう!
前回では、メモリ内のCプログラムのレイアウトを紹介し、簡単なプレゼンテーションを行いました.前回の例は比較的簡単で、プログラム内のメモリレイアウトの概略的な輪郭しか説明できません.今日は具体的なメモリアドレスを通じて、メモリ内のCプログラムのレイアウトを明確に紹介します.次に例のプログラムソースコードを示します.参考にしてください.
このコードでは,各変数のアドレスを手動で出力し,変数のアドレスによって変数のメモリにおける位置を判断し,変数がメモリレイアウトにおけるどのパーティションに属するかを確認することを目的とする.では、これらの変数はいったいどのパーティションにあるのでしょうか.dataパーティションですか、bssパーティションですか.以下はプログラムの実行結果です.参考にしてください.
プログラムの実行結果から、各変数のメモリ内のアドレスがわかりますが、これらの変数がどのメモリパーティションに属しているかは分かりません.急いではいけません.readelfツールを使ってプログラムのメモリレイアウトを見て、メモリレイアウトを通じて各メモリパーティションのアドレス範囲を見ることができます.これらは変数のアドレスに基づいて変数が存在するメモリパーティションを推定することができます.以下に詳細な結果を示します.
実行結果からプログラムの
dataパーティションは、アドレス0 x 0804 a 028から始まり、サイズは0 x 000010(16 byte)である.bssパーティションは0 x 0804 a 038から始まり、サイズは0 x 00000 c(12 byte)である.
では、プログラム内の変数のアドレスと組み合わせて、変数が存在するメモリパーティションを推定します.
また、4つの変数のアドレスはbssとdataパーティションの範囲内ではないため、これらの変数が存在するパーティションを特定することはできません.
前の章で紹介したように、重要なパーティションは4種類で、dataとbssではなく、スタックまたはスタックにしかありません.今は変数のアドレスしかありませんが、スタック領域やスタック領域のアドレス範囲があればいいです.これにより、bssとdataパーティションの変数を推定するのと同じように、メモリ内のこれらの変数のパーティションを推定することができます.
次に、プログラムのスタックとスタックパーティションを探してみましょう.前の章で紹介したproc仮想ファイルシステムを覚えていますか?スタック領域とスタック領域のメモリ領域情報を取得するために使用できます.
上記の情報から、[heap]と[stack]とマークされたパーティションは、同じ行の内容が2つのパーティションのメモリアドレス空間を示すスタック領域とスタック領域であることがわかります.
ヒープ領域:0 x 094 d 000-0 x 0966 e 000スタック領域:0 xbfde 3000-0 xbfe 04000
今、私たちはさっきどの4つの自分のパーティションを知らない変数を推定することができます.次は私たちの推定結果です.
これまで、Cプログラムのメモリ内のレイアウトを具体的なメモリアドレスで明確に示してきました.最後に直感的な図形を描いて見せて、Cプログラムのメモリモデルを直感的に見ることができます.このグラフィックは比較的簡単で、グラフィックの中で上から下を見ると、メモリアドレスが高アドレスから低アドレスに延び、各アドレスの後ろにはそのアドレスに対応するパーティション名が表示されます.
官达を见て、完全なコードは私の资源の中に置いて、みんなはここをクリックしてダウンロードして使うことができます(CSDNはまた问题が発生して、だからしばらくプログラムをアップロードすることができなくて、CSDNが问题を修复した后に、私は直ちにプログラムをアップロードして、その时みんなは私达の资源の中でプログラムをダウンロードすることができます).パソコンは人によって異なり、使用するプログラミング環境も異なる場合がありますので、視聴者の皆さんが自分のパソコンにプログラムをダウンロードして実行し、私たちが紹介した方法でメモリ内のモデルを観察することをお勧めします.
皆さん、Cプログラムのメモリレイアウトの例についてお話しします.後に何か例があるか知りたいので、次の分解を聞いてください.
前回では、メモリ内のCプログラムのレイアウトを紹介し、簡単なプレゼンテーションを行いました.前回の例は比較的簡単で、プログラム内のメモリレイアウトの概略的な輪郭しか説明できません.今日は具体的なメモリアドレスを通じて、メモリ内のCプログラムのレイアウトを明確に紹介します.次に例のプログラムソースコードを示します.参考にしてください.
int ga1;
int ga2 = 1;
int func()
{
int i = 0;
static static_la1;
static static_la2 = 3;
printf("func is running
");
printf("Address of i: %p
",&i);
printf("Address of static_la1 : %p
",&static_la1);
printf("Address of static_la2 : %p
",&static_la2);
while(i++<8)
sleep(1);
return 0;
}
int main()
{
int la1;
int la2 = 2;
int *p;
p = (int *) malloc(3*sizeof(int));
if(NULL == p)
printf("malloc failed
");
printf("Address of ga1: %p
",&ga1);
printf("Address of ga2: %p
",&ga2);
printf("Address of la1: %p
",&la1);
printf("Address of la2: %p
",&la2);
printf("Address of p: %p
",p);
func();
free(p);
p = NULL;
return 0;
}
このコードでは,各変数のアドレスを手動で出力し,変数のアドレスによって変数のメモリにおける位置を判断し,変数がメモリレイアウトにおけるどのパーティションに属するかを確認することを目的とする.では、これらの変数はいったいどのパーティションにあるのでしょうか.dataパーティションですか、bssパーティションですか.以下はプログラムの実行結果です.参考にしてください.
Address of ga1: 0x804a040
Address of ga2: 0x804a030
Address of la1: 0xbfc7e7b4
Address of la2: 0xbfc7e7b8
Address of p: 0x8ffc008
func is running
Address of i: 0xbfc7e78c
Address of static_la1 : 0x804a03c
Address of static_la2 : 0x804a034
プログラムの実行結果から、各変数のメモリ内のアドレスがわかりますが、これらの変数がどのメモリパーティションに属しているかは分かりません.急いではいけません.readelfツールを使ってプログラムのメモリレイアウトを見て、メモリレイアウトを通じて各メモリパーティションのアドレス範囲を見ることができます.これらは変数のアドレスに基づいて変数が存在するメモリパーティションを推定することができます.以下に詳細な結果を示します.
readelf -S s // readelf
There are 30 section headers, starting at offset 0x1190:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .interp PROGBITS 08048154 000154 000013 00 A 0 0 1
[ 2] .note.ABI-tag NOTE 08048168 000168 000020 00 A 0 0 4
[ 3] .note.gnu.build-i NOTE 08048188 000188 000024 00 A 0 0 4
[ 4] .gnu.hash GNU_HASH 080481ac 0001ac 000020 04 A 5 0 4
[ 5] .dynsym DYNSYM 080481cc 0001cc 000090 10 A 6 1 4
[ 6] .dynstr STRTAB 0804825c 00025c 000063 00 A 0 0 1
[ 7] .gnu.version VERSYM 080482c0 0002c0 000012 02 A 5 0 2
[ 8] .gnu.version_r VERNEED 080482d4 0002d4 000020 00 A 6 1 4
[ 9] .rel.dyn REL 080482f4 0002f4 000008 08 A 5 0 4
[10] .rel.plt REL 080482fc 0002fc 000038 08 A 5 12 4
[11] .init PROGBITS 08048334 000334 000023 00 AX 0 0 4
[12] .plt PROGBITS 08048360 000360 000080 04 AX 0 0 16
[13] .text PROGBITS 080483e0 0003e0 0002a2 00 AX 0 0 16
[14] .fini PROGBITS 08048684 000684 000014 00 AX 0 0 4
[15] .rodata PROGBITS 08048698 000698 0000dc 00 A 0 0 4
[16] .eh_frame_hdr PROGBITS 08048774 000774 000034 00 A 0 0 4
[17] .eh_frame PROGBITS 080487a8 0007a8 0000d0 00 A 0 0 4
[18] .init_array INIT_ARRAY 08049f08 000f08 000004 00 WA 0 0 4
[19] .fini_array FINI_ARRAY 08049f0c 000f0c 000004 00 WA 0 0 4
[20] .jcr PROGBITS 08049f10 000f10 000004 00 WA 0 0 4
[21] .dynamic DYNAMIC 08049f14 000f14 0000e8 08 WA 6 0 4
[22] .got PROGBITS 08049ffc 000ffc 000004 04 WA 0 0 4
[23] .got.plt PROGBITS 0804a000 001000 000028 04 WA 0 0 4
[24] .data PROGBITS 0804a028 001028 000010 00 WA 0 0 4
[25] .bss NOBITS 0804a038 001038 00000c 00 WA 0 0 4
[26] .comment PROGBITS 00000000 001038 00004f 01 MS 0 0 1
[27] .shstrtab STRTAB 00000000 001087 000106 00 0 0 1
[28] .symtab SYMTAB 00000000 001640 0004c0 10 29 47 4
[29] .strtab STRTAB 00000000 001b00 0002be 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
実行結果からプログラムの
dataパーティションは、アドレス0 x 0804 a 028から始まり、サイズは0 x 000010(16 byte)である.bssパーティションは0 x 0804 a 038から始まり、サイズは0 x 00000 c(12 byte)である.
では、プログラム内の変数のアドレスと組み合わせて、変数が存在するメモリパーティションを推定します.
Address of ga1: 0x804a040 // bss(0x0804a038), bss
Address of ga2: 0x804a030 // data(0x0804a028), bss, data
Address of static_la1 : 0x804a03c // bss(0x0804a038), bss
Address of static_la2 : 0x804a034 // data(0x0804a028), bss, data
また、4つの変数のアドレスはbssとdataパーティションの範囲内ではないため、これらの変数が存在するパーティションを特定することはできません.
Address of la1: 0xbfc7e7b4 // bss(0x0804a038), bss
Address of la2: 0xbfc7e7b8 // bss(0x0804a038), bss
Address of p: 0x8ffc008 // bss(0x0804a038), bss
Address of i: 0xbfc7e78c // bss(0x0804a038), bss
前の章で紹介したように、重要なパーティションは4種類で、dataとbssではなく、スタックまたはスタックにしかありません.今は変数のアドレスしかありませんが、スタック領域やスタック領域のアドレス範囲があればいいです.これにより、bssとdataパーティションの変数を推定するのと同じように、メモリ内のこれらの変数のパーティションを推定することができます.
次に、プログラムのスタックとスタックパーティションを探してみましょう.前の章で紹介したproc仮想ファイルシステムを覚えていますか?スタック領域とスタック領域のメモリ領域情報を取得するために使用できます.
./s & //
[1] 2736 // , PID
Address of ga1: 0x804a040 // ,
Address of ga2: 0x804a030
Address of la1: 0xbfe01cf4
Address of la2: 0xbfe01cf8
Address of p: 0x964d008
func is running
Address of i: 0xbfe01ccc
Address of static_la1 : 0x804a03c
Address of static_la2 : 0x804a034
cat /proc/2736/maps // proc
08048000-08049000 r-xp 00000000 08:13 22415696 /home/talk8/s
08049000-0804a000 r--p 00000000 08:13 22415696 /home/talk8/s
0804a000-0804b000 rw-p 00001000 08:13 22415696 /home/talk8/s
0964d000-0966e000 rw-p 00000000 00:00 0 [heap]
b75b7000-b75b8000 rw-p 00000000 00:00 0
b75b8000-b7761000 r-xp 00000000 08:16 6444 /lib/i386-linux-gnu/libc-2.19.so
b7761000-b7763000 r--p 001a9000 08:16 6444 /lib/i386-linux-gnu/libc-2.19.so
b7763000-b7764000 rw-p 001ab000 08:16 6444 /lib/i386-linux-gnu/libc-2.19.so
b7764000-b7767000 rw-p 00000000 00:00 0
b777e000-b7781000 rw-p 00000000 00:00 0
b7781000-b7782000 r-xp 00000000 00:00 0 [vdso]
b7782000-b77a2000 r-xp 00000000 08:16 6459 /lib/i386-linux-gnu/ld-2.19.so
b77a2000-b77a3000 r--p 0001f000 08:16 6459 /lib/i386-linux-gnu/ld-2.19.so
b77a3000-b77a4000 rw-p 00020000 08:16 6459 /lib/i386-linux-gnu/ld-2.19.so
bfde3000-bfe04000 rw-p 00000000 00:00 0 [stack]
上記の情報から、[heap]と[stack]とマークされたパーティションは、同じ行の内容が2つのパーティションのメモリアドレス空間を示すスタック領域とスタック領域であることがわかります.
ヒープ領域:0 x 094 d 000-0 x 0966 e 000スタック領域:0 xbfde 3000-0 xbfe 04000
今、私たちはさっきどの4つの自分のパーティションを知らない変数を推定することができます.次は私たちの推定結果です.
Address of la1: 0xbfe01cf4 // ,
Address of la2: 0xbfe01cf8 // ,
Address of p: 0x964d008 // ,
Address of i: 0xbfe01ccc // ,
これまで、Cプログラムのメモリ内のレイアウトを具体的なメモリアドレスで明確に示してきました.最後に直感的な図形を描いて見せて、Cプログラムのメモリモデルを直感的に見ることができます.このグラフィックは比較的簡単で、グラフィックの中で上から下を見ると、メモリアドレスが高アドレスから低アドレスに延び、各アドレスの後ろにはそのアドレスに対応するパーティション名が表示されます.
官达を见て、完全なコードは私の资源の中に置いて、みんなはここをクリックしてダウンロードして使うことができます(CSDNはまた问题が発生して、だからしばらくプログラムをアップロードすることができなくて、CSDNが问题を修复した后に、私は直ちにプログラムをアップロードして、その时みんなは私达の资源の中でプログラムをダウンロードすることができます).パソコンは人によって異なり、使用するプログラミング環境も異なる場合がありますので、視聴者の皆さんが自分のパソコンにプログラムをダウンロードして実行し、私たちが紹介した方法でメモリ内のモデルを観察することをお勧めします.
皆さん、Cプログラムのメモリレイアウトの例についてお話しします.後に何か例があるか知りたいので、次の分解を聞いてください.