プロが教える店舗&オフィスのセキュリティ対策術

https://oshiete.goo.ne.jp/qa/12563031.html
のNo.5の回答を解説して頂けないでしょうか? 例えば、a.c と b.c というふたつのソースコードを書いたとします。a.c には
b.c に含まれる func() という関数を呼び出しているとします。
a.c と b.c をコンパイルしオブジェクト a.obj と b.obj をコード生成した状態では a.obj 内では func() が存在するのかどうかまだわかっていません。a.obj と b.obj をリンク処理し実行可能ファイルを生成した時点で、はじめて func() の呼び出し元と呼び出し先がリンクされてアドレス(セグメント内のオフセット)が決まります。
で、すみません。①オブジェクトとはなんでしょうか? ②セグメントとはなんでしょうか?③オフセットとはなんでしょうか?教えていただけると幸いです。大変恐縮ですが。

gooドクター

A 回答 (3件)

ご質問者様が発信する機関銃のようなご質問が、この「C言語・C++・C#」エリアに嵐を巻き起こしているように見えます。

多くの回答者が日々「どのようにしてご質問者に納得頂くか...」熟慮を重ねているように思われます。私は僅かな知識しか持ち合わせていないのですが、少しだけこの論争に首を突っ込んでみて、うまく行かないようならばすぐに引っ込めたいと思います(亀みたいにね)。

● ...No.5の回答を解説して...
多くの回答者が仰るように...また、ご質問者がどの程度C言語プログラミングの知識技量をお持ちなのか、未だにご提示がないことから、実際の作業に即してご説明しましょう。

ファイル: a.c         ファイル: b.c
1                1
2 #include <stdio.h>      2 #include <stdio.h>
3                3
4 // prototype         4 void func ( void )
5 void func ( void );      5 {
6                6 printf ( "This is func\n" );
7 int main ( void )       7 }
8 {
9 printf ( "Start main\n" );
10
11 func ();
12
13 printf ( "End main\n" );
14 return ( 0 );
15 }

このソースファイルをコンパイルするために、Linuxで一般的なgccを使用してみます。上記の2つのソースファイルをオブジェクトファイルに変換し、リンカを用いて実行ファイルを作成するためには次のコマンドを実行します。

$ gcc -c a.c -o a.obj
$ gcc -c b.c -o b.obj
$ gcc a.obj b.obj -o exe

ソースファイルそれぞれから、オブジェクトファイル"a.obj", "b.obj"を、そして実行ファイル"exe"を作成していることが判るでしょう。このプログラムを実行すれば、当然以下の結果が得られます。

$ ./exe
Start main
This is func
End main
$

NO5様の回答の中で重要と思われるのは『名前(シンボルとも言う)』です。例に示した単純なソースファイルでは名前は2つ、"main","func"が出てきますが、変数を使用する場合でも『名前』が使われることをご存知でしょう。
ソースファイルでは様々なものに名前を付けて、さらにそれを『呼ぶ』ことで利用していることにご注意下さい。
また、これらの『名前』は、実行ファイルでは場所、位置、あるいはアドレスに置き換えられることはご理解いただけるでしょう。コンパイラ(リンカ)が行うこの処理を『名前解決』と呼びます。

上の例を参照すれば、『名前解決』が可能なのは「gcc a.obj b.obj -o exe」の処理であることにご注意下さい。

さらにまた、ソースファイルを記述する段階で場所を指定することの愚かしさ、または不便さは、ご説明の必要もないと思われます。

ファイル: a.c
1
2 #include <stdio.h>
3
4
5
6
7 int main ( void )
8 {
9 printf ( "Start main\n" );
10
11 jump [b.cファイルの4行目]
12
13 printf ( "End main\n" );
14 return ( 0 );
15 }

b.cファイルを少しでも改造したら、すぐに行位置などは変わってしまいます。人間がソースファイルを記述する際には、場所ではなく名前を使う方が全然楽なはずです。

●オブジェクトとはなんでしょうか...
Object(オブジェクト)の意味は辞書を確認いただくとして、但し大した意味のある単語ではないことにご注意下さい。NO5様の回答、及びご質問者様自身の質問にも出てくるように、ここで説明が要求されているのはオブジェクト"ファイル"です。
ご質問者様が何処かにお書きになっていた「オブジェクト指向」などとは意味が違います。
オブジェクトファイルはこれまでの説明のとおり、ファイル"a.obj"と"b.obj"を意味しています。ファイルそのものです。

何故、これらファイルを"オブジェクト"と呼ぶようになったかですが、私は大した意味はないと思いますよ。ご質問者様はこのファイルに名前(漢字でね)を付けるとしたら、どの様にしますか...私なら「既にバイナリファイルに変換されていて、普通にはエディタで中身を見ることもできないし...名前解決は実行されていない半チクファイルだし...」ということで...

『名前解決実行前のバイナリ半チクファイル』

と呼びます。しかしながら、誰かがこのファイルを指して「オブジェクトファイル」と言ったんだと思いますよ。そりゃあ『名前...チクファイル』よりも「オブジェクトファイル」のほうがいいでしょう。

●セグメントとはなんでしょうか...
実行ファイルを起動する状況をお考え下さい。ストレージに置かれた実行ファイルが読み込まれ、メモリ上に展開されます。この時、メモリ上では利用目的により異なる種類の、複数の領域が作成されます。この領域をセグメントと言い...

コードセグメント
データセグメント
スタックセグメント
ヒープセグ...

などに分類されます。但し現代のコンピュータではプログラマはセグメントをほとんど意識することはないはずで、私のような愚かな人間が...

int *p = 0;
*p = 35;

などに類することをやってしまい...プログラム実行時に...

Segmentation fault (core dumped)

が出て驚くくらいでしょう。但し、8ビットや16ビットコンピュータの「組み込みプログラムの領域」では、利用できるセグメントのサイズに注意が必要となり(16ビットで最大64kb)、プログラマがセグメントの管理も行わなければならなくなります(これは実に厄介です...と思います。)。

●オフセットとはなんでしょうか...
前述のセグメントの先頭番地を"0"とした時のある特定事物の位置/アドレスをオフセットと呼びます。つまり、物理メモリのアドレスとは違うオフセットアドレスをソフトウエアは見たり書いたりしているということです。
Linuxでは"nm"というコマンドがあり、オブジェクトファイルや実行ファイルに含まれるシンボル(名前)をリストにして表示してくれます。
試みにこの回答で使用したexeプログラムをnmで解析すると次の結果が表示されます。

$ nm ./exe
0000000000403e00 d _DYNAMIC
0000000000404000 d _GLOBAL_OFFSET_TABLE_
0000000000402000 R _IO_stdin_used
    |       |         |
    |       |         |
00000000004011c4 T _fini
0000000000401000 T _init
0000000000401040 T _start
0000000000404030 b completed.0
0000000000404020 W data_start
0000000000401080 t deregister_tm_clones
0000000000401120 t frame_dummy
0000000000401146 T func
0000000000401122 T main
    |       |         |
    |       |         |

シンボル名と共にアドレスが表示されますが、例えば"func"や"main"のアドレスが意味するのは、コードセグメントの中でそれぞれのシンボルが位置するオフセットアドレス、であるはずです。

●その他...
私の回答には誤りが含まれているかもしれません。ご質問者、あるいは他の回答者の中でお気づきの点がありましたらご指摘下さい。
    • good
    • 0

本当に分かりたいのであれば、このあたりの本を読むのでしょうか。


http://www.amazon.co.jp/dp/4296000195
    • good
    • 0

ご質問者様は、C言語のプログラムをいくつ位作った経験がありますか。


開発環境は何をお使いでしょうか。あまり経験がないのではないかと察します。
自分で作って、動かしていることが大事です。
問  歩くということはどういうことですか。
回答 まず、右足を前に出します。
   次に、左足を前に出します。また右足を出し、以下繰り返します。
問  左足を出すとき、右足はどこにありますか。
   また、左足を出した後、右足はどこにありますか。
回答 左足を出すとき、右足は左足より前にあります。
   左足を出した後、右足は左足より後ろにあります。
問  右足はなぜ左足より後ろに行ったのですか。
このような問が永遠と繰り返すようです。
やってみれば疑問は解けなくても、それはどうでもよくなるでしょう。
解説書でも、「ここでは説明はしませんが、呪文だと思ってください。」という文言がよく出て来ます。
    • good
    • 3
この回答へのお礼

①オブジェクトの意味は以下のURLの事でしょうか?教えていただけると幸いです。
https://wa3.i-3-i.info/word1119.html
②セグメントの意味は以下のURLの事でしょうか?教えていただけると幸いです。すみません。
https://wa3.i-3-i.info/word12125.html
③オフセットの意味は以下のURLの事でしょうか?教えていただけると幸いです。すみません。
https://wa3.i-3-i.info/word11923.html

お礼日時:2021/09/12 21:07

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

gooドクター

このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング