こんにちは、ふじかーです。
前回書いた
.bssセクションのグローバル変数の初期化についての記事、
組み込み屋さんには当たり前の事と言われるかもしれませんが
本当にそうなってるか気になったので、実際に動かして確認してみました。
セクション概要
プログラムはメモリに配置されて実行されるわけですが
メモリ上にはプログラム内の「機械語」や「変数」「定数」など、各種用途に分けて配置され
その単位のことをセクションといいます。
と、ここまでは前回記載しましたが、
これ以外にもプログラム実行中、関数内のローカル変数等が
使用されるときに配置される「スタック領域」がありますね。
上記のセクション は
プログラムをコンパイル(リンク)した時点でアドレスとサイズが決まり、
実行中に変わる事はない、静的な領域
なのに対し、
スタック領域 は
プログラム実行中、使用時に一時的に確保されたり開放されたりする、
動的な領域
という違いがあります。
テストプログラム
それらを確認するため
変数の値や配置アドレスを出力するだけのプログラムを書いてみます。
#include <stdio.h>
int global_int1 = 111; //global 初期値あり
int global_int2; //global 初期値なし
int global_int3 = 0; //global 初期値0
const char global_chr1[] = "abc"; //global constあり
char global_chr2[] = "def"; //global constなし
int section_test(int param);
int main(void)
{
int ret = 0;
ret = section_test(123);
return 0;
}
int section_test(int param)
{
int local_int1 = 222; //local 初期値あり
int local_int2; //local 初期値なし
int local_int3 = 0; //local 初期値0
static int local_int4 = 333; //local static 初期値あり
static int local_int5; //local static 初期値なし
static int local_int6 = 0; //local static 初期値0
printf("\n■関数\n");
printf("main() (0x%X)\n", &main);
printf("section_test() (0x%X)\n", §ion_test);
printf("\n■引数\n");
printf("param (0x%X) = %d \n", ¶m , param);
printf("\n■グローバル変数\n");
printf("global_int1 初期値あり (0x%X) = %d \n", &global_int1 , global_int1);
printf("global_int2 初期値なし (0x%X) = %d \n", &global_int2 , global_int2);
printf("global_int3 初期値0 (0x%X) = %d \n", &global_int3 , global_int3);
printf("global_chr1 constあり (0x%X) = %s \n", &global_chr1 , global_chr1);
printf("global_chr2 constなし (0x%X) = %s \n", &global_chr2 , global_chr2);
printf("\n■ローカル変数\n");
printf("local_int1 初期値あり (0x%X) = %d \n", &local_int1 , local_int1);
printf("local_int2 初期値なし (0x%X) = %d \n", &local_int2 , local_int2);
printf("local_int3 初期値0 (0x%X) = %d \n", &local_int3 , local_int3);
printf("\n■静的ローカル変数(static)\n");
printf("local_int4 初期値あり (0x%X) = %d \n", &local_int4 , local_int4);
printf("local_int5 初期値なし (0x%X) = %d \n", &local_int5 , local_int5);
printf("local_int6 初期値0 (0x%X) = %d \n", &local_int6 , local_int6);
return 0;
}
各種変数をprintf出力するだけなのに、意外と長くなってしまいました
これを例によってVS Codeでコンパイルして、動かしてみます。
実行結果が
また、前回同様 objdump で実行ファイルの内容を確認しておきます。
メモリ配置確認
さて、実際の配置はどうなっているでしょうか。
テストプログラムでの実行結果を絵にすると、こんな感じになりました。
|
各変数は、想定したセクションに置かれていました |
・・・とまぁ結果としては大体想定通り動いているようです。
「ほぉ、確かにこんな風に配置されるんだな」
とイメージ出来ていると、もしかしたら
いずれ業務で会話に出たとき役に立ったりするかもしれません。
プログラム初心者の方は参考にしてください。
※ここまで書いて、せっかくだったら「ヒープ領域」も
追加しときゃよかったかな・・・とも思いましたが、
まぁ想像以上にゴチャゴチャしてきたし、今回はここまでとします。。