はじめに
現在、私は立場上、業務でコードを書くことが殆どないのですが、とあることをきっかけに、C#に入門しようと思い立ちました。
C#の入門書を購入して早速勉強を始めてみましたが、プログラミング入門書のご多分に漏れず、出ましたMainメソッドの説明。
・C#は、Mainメソッドを探して最初に実行します
・これをエントリーポイントといいます
ふと、ここで気になりました。
・誰がMainメソッド探して呼ぶの?
・何を元にMainメソッドがどこにあるのかを把握するのか?
業界歴を四捨五入すると20年になる年数ながら、そこまで調べたことなかったなーと思い、この際調べてみました。
なお、今回はC言語における仕組みについて調べました。
書籍として、どんぴしゃのものがあり、そこでC言語が扱われていたためです。
また、勿論言語によって委細異なるとは思いますが、概念的な仕組みとしてはだいたい一緒じゃないかな?と思って、他の言語の仕組みは調べていません。
C言語から作られたプログラムにおける、mainが呼び出される仕組み
調べてみたら、以下の書籍でまんま紹介されていそうだったので、早速図書館で借りて読みました。
書籍のうち、「第五章 main()関数の前と後」に詳細が記載されていますが、かいつまんでいうと、
- Linuxの実行ファイルのメタ情報(ELFフォーマット)にある、
Entry point address
のアドレスからプログラムが開始される -
Entry point address
のアドレスは、標準Cライブラリ(glibc)にある_start()
関数のアドレスであり、プログラムはまず_start()
から処理が恥じます -
_start()
でmain関数の引数とmain関数のアドレスをスタックに積んで、__libc_start_main()
を呼び出す -
__libc_start_main()
でmain関数を呼び出す
という感じでした。
ちなみにこのあたりの情報は、Web記事としても挙がっていました。
厳密に考えると、main関数はエントリーポイントではない
ということになるのですが、抽象的に捉えると実質はエントリーポイントとして考えていい、ということで入門書ではこういった説明になっているのでしょうね。
main関数の位置はどこを見ればわかるのか?
ここまで、実行ファイルを起動した際の、main関数の呼び出され方について調べたことを書きました。
そもそも、main関数の位置ってどこにあるのでしょうか?
(勿論実行ファイルの中にある、とは思うものの具体的にどこ?というのは知らなかったので調べました)
実行ファイルのメタ情報(ELFフォーマット)のどこかにあると思うのでフォーマットの定義を調べてみると、Symbole Table Sectionという、関数や変数などのシンボルに関するメタ情報があり、その中のValueに関数のアドレス(相対/仮想アドレス)の情報があるようです。
このメタ情報を参照して、main関数(だけじゃなく他の関数の呼び出しでも)の場所を特定している、というのが理解できました。
メタ情報がどのようにできるか、はコンパイラやリンカのお仕事になると思いますが、今回はそこまでは深く調べませんでした(また機会があれば調べてみようと思います)。
おわりに
知りたかったことは全て以下の記事にあったとさ。
自分の調べた内容の答え合わせ的に参照させて頂きました、感謝。
時間があったら、入門中のC#や、昔やってたDelphiなんかの仕組みも調べてみようかなと思います。