質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

GCC

GCCはGNU Compiler Collectionの略です。LinuxのC言語コンパイラのデファクトスタンダードであり、数多くの他言語やプラットフォームサポートもします。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

2552閲覧

アドレスが一致しません。

strike1217

総合スコア651

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

GCC

GCCはGNU Compiler Collectionの略です。LinuxのC言語コンパイラのデファクトスタンダードであり、数多くの他言語やプラットフォームサポートもします。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2017/07/24 08:27

実験コードを書きますね。

スタックの先頭アドレスを取得します。

C++

1#include <stdio.h> 2#include <unistd.h> 3 4extern void* __libc_stack_end; 5 6void* get_linux_stack_base() 7{ 8 unsigned long long pagesize = sysconf(_SC_PAGESIZE); 9 return (void*)(((unsigned long long)__libc_stack_end + pagesize) & ~ (pagesize - 1)); 10} 11 12int main() 13{ 14 int t; 15 scanf("%d", &t); 16 printf("end:%p, base:%p\n", __libc_stack_end, get_linux_stack_base()); 17} 18

C++でコンパイルしていますが、おそらくCでも大丈夫だと思います。
scanf()はなくても良いです。待機させるためにあります。
結果は、、、
__libc_stack_end = 0x7fffffffd630
0x7fffffffe000 となりました。

ところが、/proc/PID/mapsを覗くと・・・

7ffff7ffe000-7ffff7fff000 rw-p 00000000 00:00 0 7ffffffdd000-7ffffffff000 rw-p 00000000 00:00 0 [stack]

となっています。(左側がスタートアドレスです。)
どちらも開始アドレスが一致していません。
なぜでしょうか??

どちらかが間違っているんですかね??

ちょっと近い話が書いてある箇所を見つけました。

ダイナミンクリンカローダや共有ライブラリなどをreadelf -S で見ても上記のように固定のアドレスが設定されているわけではありません。

??
ではこのコマンド(readelfやproc)によって表示されているアドレスは何でしょうか??

ちなみに、「ALSR」は無効化しています。
これは・・・「ALSR」が有効の場合の話をしているんでしょうか??

環境はLinux 64bit GCC です!

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

回答ではないけど、似たような場面で使えそうなアドバイスを。

scanf()はなくても良いです。待機させるためにあります。

待機させるのは、プロセスIDを調べ、/proc/PID/mapsを表示するためですが、
プログラマらしく対策しましょう。お試しあれ。

C

1#include <stdio.h> 2#include <unistd.h> 3#include <sys/types.h> 4#include <stdlib.h> 5(途中省略) 6int main(void) 7{ 8 char cmdline[80]; 9 10 sprintf(cmdline, "cat /proc/%d/maps | grep stack", getpid()); 11// printf("$ %s\n", cmdline); // 何をしてるか確認したいなら 12 system(cmdline); 13 printf("end:%p, base:%p\n", ...

投稿2017/07/25 12:55

rubato6809

総合スコア1380

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

strike1217

2017/07/25 12:56

なるほど! 確かにそちらの方がカッコイイですね。
guest

0

ベストアンサー

__libc_stack_end が返す値は、スタートアップルーチンがスタックを消費する分だけずれるようです。 /proc/PID/maps の結果とずれるのはそのせいでしょう。

共有オブジェクトは一般に PIC (位置独立コード) として生成します。 これは再配置することを前提とした形式です。 共有オブジェクトはメインとなる実行ファイルと一緒にロードされて使われるわけですが、メインの実行ファイルは他の共有オブジェクトも利用するかもしれません。 共有オブジェクトは他の共有オブジェクトの情報を (コンパイル時には) 知れるとは限りませんので、配置するアドレスを決め打ちにしてしまうと位置が重なってしまったりして不都合なのです。 なので、ローダが適切にメモリを割当てる仕組みを持っており、共有オブジェクトの側では具体的なメモリアドレスではなく割り当てに必要な情報を持つという形になります。

投稿2017/07/24 12:56

SaitoAtsushi

総合スコア5437

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

strike1217

2017/07/24 13:19

/proc/PID/mapsの方が正確なスタート位置で、__libc_stack_endはズレているんですね!! スタートアップルーチンとはこの場合何でしょうか? ダイナミックリンカローダですか? _startセクションの方ですかね? main()以前のものすべて含まれるんでしょうか?
strike1217

2017/07/24 13:34 編集

共有オブジェクトの場合、再配置を前提とした形式のファイルなので、実行時にアドレスを決定するので「固定ではない」という意味ですね!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問