スタックサイズの見積り
■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん
2005/12/14(水) 13:25:43コンパイラのデフォルト値のまま、変えたことがない人も多いかと思います。
このスレッドでは、スタックサイズを適切に見積もる方法について議論します。
0002デフォルトの名無しさん
2005/12/14(水) 13:30:39/ /__/ / /
/\ / / || / / /
/ \ / / /
__|_
/ / \ ||
/ | ―― / \ ――
/ | / \
__ __
/ / /
/ /__/ ――
/
/\___/ヽ
/'''''' '''''':::::::\
. |(〇), 、(〇)、.:|
| ,,ノ(、_, )ヽ、,, .::::|
. | `,rェェェ、 ' .:::::::|
\ |,r-r-| .::::/
,,.....イ.ヽヽ、`ニニ´ーノ゙-、.
: | '; \_____ ノ.| ヽ i
| \/゙(__)\,| i |
> ヽ. ハ | ||
地球のみんな、オラにスタックを分けてくれ――!!!
0003デフォルトの名無しさん
2005/12/14(水) 13:36:130004デフォルトの名無しさん
2005/12/14(水) 13:49:17***終了***
0005デフォルトの名無しさん
2005/12/14(水) 20:25:46スレを1本使って議論するだけ奥の深い話だと思います。
質問スレで片付くような簡単な問題なら、
あなたが、ここで1レスで解決してみ。
0006デフォルトの名無しさん
2005/12/14(水) 20:27:46***終了***
0007デフォルトの名無しさん
2005/12/14(水) 21:31:560008デフォルトの名無しさん
2005/12/14(水) 21:39:04OSによっては違うものがあった希ガス
>>2 ワロタ
0009デフォルトの名無しさん
2005/12/14(水) 21:50:26スタックサイズを気にしなくて済むようにヒープをがんがん使うんだろ。
0010デフォルトの名無しさん
2005/12/14(水) 21:52:50***終了***
0011デフォルトの名無しさん
2005/12/14(水) 22:23:52プロセスの仮想メモリ空間はたっぷりあるから、100MBくらい割り当てておけ。
というのでもよかったけど、
最近は仮想メモリ空間はさほど広くないし、
マルチスレッドなので100MBずつ割り当てたら大変だね。
そこで64ビットですよ。
0012デフォルトの名無しさん
2005/12/15(木) 05:35:42組み込んでいた場合はスタックオーバーフローしないかと冷や冷やでしたが、
いざ検証チームに移ったら長いファイル名でのバグ出しが楽しくなりました。
0013デフォルトの名無しさん
2005/12/15(木) 05:44:56想像もつかんが!
0014デフォルトの名無しさん
2005/12/15(木) 05:47:27無知乙
0015デフォルトの名無しさん
2005/12/15(木) 06:01:38内部変数でこんなの定義しているヤツだろ
char buff[10000000];
0016デフォルトの名無しさん
2005/12/15(木) 06:29:36static char buff[10000000];
で回避可能
0017デフォルトの名無しさん
2005/12/15(木) 07:37:57***終了***
0018デフォルトの名無しさん
2005/12/15(木) 07:40:250019デフォルトの名無しさん
2005/12/15(木) 08:00:380020デフォルトの名無しさん
2005/12/15(木) 08:17:36可能
0021デフォルトの名無しさん
2005/12/15(木) 15:50:12副作用が大きいじゃん。
>>18
スタック上にあるオブジェクト(auto変数とか関数の引数とか)のポインタを比較すれば桶。
0022デフォルトの名無しさん
2005/12/15(木) 15:59:42スタックオーバーフローが起きる可能性は激減するの?
もちろんリターンアドレスの蓄積でオーバーフローするような深すぎる再帰は別として。
教えてエロい人。
0023デフォルトの名無しさん
2005/12/15(木) 16:05:27__fastcallとは何ですか?
0024デフォルトの名無しさん
2005/12/15(木) 20:30:08引数での実体渡しはスタックを喰うからなぁ。特に再帰では控えるべきだろうな。
0025デフォルトの名無しさん
2005/12/15(木) 20:33:06それだと再帰の一時エリアとして使えないじゃん。
malloc/freeやnew/deleteでないと。
0026デフォルトの名無しさん
2005/12/15(木) 21:43:18Pascal
0027デフォルトの名無しさん
2005/12/15(木) 21:45:44普通const参照にするだろ。(Cならconstポインタ)
002823
2005/12/15(木) 21:59:46えーとそれは、呼び出し規約の違いと言うことですか?
Pascalだと一般的なCとは逆順で積むのかな?
するってぇとfastcallはレジスタ渡し?
なんだか奇体なコンパイラだねぇ。
0029デフォルトの名無しさん
2005/12/15(木) 22:06:36末尾再帰の形にしたのなら人の手でループにできる。
0030デフォルトの名無しさん
2005/12/15(木) 23:42:21自前のループとスタックなデータ構造で実装すれば、
ヒープは食うかもしれないが、CPUのスタックは食わないよね。
0031デフォルトの名無しさん
2005/12/15(木) 23:44:37スタックをどこまで使ったのか、
知りたいとは思う。
各関数の入り口あたりでスタックポインタをチェックして、
その最小値を保持するようにすればいいのかな。
それとも、メモリを特定のパターンで埋めておき、
あとで、どこまで書き換えられたのかチェックすればいいのかな。
0032デフォルトの名無しさん
2005/12/16(金) 01:08:08しかし折角のアルゴリズムとコード記述の簡潔さと美麗さが失われる罠
0033デフォルトの名無しさん
2005/12/16(金) 02:07:12DOSの頃は特定パターンで埋めとく方法だった。
今はどうなってんのか知らん。
「あとで」と言うのがどの時点かでだいぶ変わって来る。
0034デフォルトの名無しさん
2005/12/16(金) 02:52:57今のWindowsなんかだとOSのメモリ管理機構を通すし、スタックもプロセスごと
に割り当てられるから、プログラム終了後に確認なんてできないだろう。
0035デフォルトの名無しさん
2005/12/16(金) 10:52:09その関数をatexit()に登録しておくとか、そもそもスタートアップルーチンを差し替えるとか。
いずれにしても、デバッグ用のスタートアップルーチンを持っている開発環境なら既にやっていることだ。
0036デフォルトの名無しさん
2005/12/16(金) 11:26:42mainで最初にスタックのアドレス覚えておいて
深くなる関数内で同様にauto変数のアドレス調べればいい
0037デフォルトの名無しさん
2005/12/16(金) 14:05:210038デフォルトの名無しさん
2006/05/05(金) 15:39:47自己呼び出しな関数が一つでもあれば破綻する方法だが。
0039デフォルトの名無しさん
2006/05/06(土) 06:35:04遅レスだが、スレッド単位でスタックサイズを変えられない OS ってあるの?
0040デフォルトの名無しさん
2006/05/10(水) 18:19:5564ビットにして、実質上無限になるように、それぞれの領域を離しておくべきだ。
1プロセスで1000スレッドとかのプロセスはどーするんだって? 紫蘭がナ。
0041デフォルトの名無しさん
2006/05/10(水) 20:15:17勿論セグメントを使わないWindowsやその他大抵のOSは使っていない。
0042デフォルトの名無しさん
2006/05/10(水) 20:46:16アドレス空間が足りなくなるから、あらかじめスタックサイズを指定して、アドレス空間を節約する必要があるのですよ。
0043デフォルトの名無しさん
2006/05/12(金) 16:04:040:32 モデルではなくちゃんと ss 使えばメモリ空間的にも大丈夫、って話では?
0044デフォルトの名無しさん
2006/05/12(金) 23:10:36AdvancedWindows嫁
0045デフォルトの名無しさん
2006/05/13(土) 12:38:28もし、そうすると、
ポインタを単なるスカラー値ではなく、
アドレス値に加えてセグメント値も持つベクトル値にする必要があるよ。
16ビットの頃の、farポインタって奴みたいにさ。
0046デフォルトの名無しさん
2006/05/13(土) 17:59:46middleモデル、largeモデルなんて忘れたぜ
0047デフォルトの名無しさん
2006/05/13(土) 19:36:33いやそれは必要ないし、アプリ側では物理アドレスがどこかなんて判らない。
ただ、ローカル変数なんかのアクセスにいちいち SS: が必要になるんで、
当時は嫌だったんだろうな。
今となってはそうすべきだったと思えるが
0048デフォルトの名無しさん
2006/05/13(土) 23:52:54たしかに忘れてるようだな。
middleモデルじゃなくてmediumモデルじゃなかったか?
0049デフォルトの名無しさん
2006/05/14(日) 00:52:340050デフォルトの名無しさん
2006/05/14(日) 07:28:480051デフォルトの名無しさん
2006/05/14(日) 15:09:54> いやそれは必要ないし、アプリ側では物理アドレスがどこかなんて判らない。
物理アドレスの話なんて誰もしていないぞ。
> ただ、ローカル変数なんかのアクセスにいちいち SS: が必要になるんで、
> 当時は嫌だったんだろうな。
まだわかっていないようだな。
スタック上のオブジェクトへのポインタ
ヒープ上のオブジェクトへのポインタ
この2つを区別しなくてはいけないので、
32ビットの仮想アドレス値に加えて、
どのセグメントレジスタを使うのかを示すものが必要になる。
どちらか片方しか受け取れない関数なんてのは使いにくいので、
両方に対応することになるわけで、オーバーヘッドが馬鹿馬鹿しいよ。
ポインタの指す先にアクセスする度に、DSとSSどちらを使うかで条件分岐するなんてさ。
0052デフォルトの名無しさん
2006/05/14(日) 16:45:26そうだったな。
BPをSPの代わりにローカルスタックとして使うしかないか
0053デフォルトの名無しさん
2006/05/14(日) 22:04:37ローカルスタックって何さ。
関数ないローカル変数ならスタック上に確保した後BPでアクセスするのが常套手段だけどそのこと言ってるわけじゃないよね?
つーか、世の中x86だけじゃないんだから少しは他も勉強してみたら?
0054デフォルトの名無しさん
2006/05/15(月) 05:54:31ごめん。
PCとレジスタの保存は SS:SP に ローカル変数は BPをスタックとして使って保存させるという意味
0055デフォルトの名無しさん
2006/05/15(月) 18:36:21何を言いたいのか、わからない。
スタックとヒープを別々のアドレス空間に取ることで発生する問題を、
> BPをSPの代わりにローカルスタックとして使う
ことで、どのように解決するのか、くわしく説明してよ。
0056デフォルトの名無しさん
2006/05/15(月) 19:50:47具体的に言うと、
関数の頭で、BPをPUSH した後
必要サイズだけ BP を マイナスする そして、BP相対でローカル変数をアクセスする
関数の終わりで BP をPOPして RET する。
BPの指す領域はデータ領域なので、この領域を他の関数で参照する時には、当然
問題は発生しない。
関数の帰り番地、BPの保存とか
関数の途中で他のレジスタの保存が必要になれば
PUSH/POPする。 これはスタック領域だけど、この領域は参照されるべき領域じゃない
0057デフォルトの名無しさん
2006/05/15(月) 20:03:34これはハードウエアスタックではないのでBPより前に書いても壊れる心配はない
0058デフォルトの名無しさん
2006/05/15(月) 20:17:16スタック上にデータを置かずにBPでデータ専用スタックを使うって話ですよね。
そのデータ専用スタックについて、
>>40-45の問題が発生するだけのような・・・
0059デフォルトの名無しさん
2006/05/15(月) 20:33:59>BPの指す領域はデータ領域なので、
BPのデフォルトのアクセス先はSS
0060デフォルトの名無しさん
2006/05/15(月) 20:36:44そうなんだよね。 だからいちいち DS: が必要だ
0061デフォルトの名無しさん
2006/05/15(月) 22:43:53それは問題の解決になっていないよ。
スタック上の、ポインタで参照されるオブジェクトを、
ヒープなどと同じアドレス空間に設けた別のスタックに移す
ということでは、>>58さんの言うように、別のスタックの空間の割り当ての問題がでてくる。
それに、スタックからポインタで参照されるオブジェクトを追い出してしまったら、
必要なスタックサイズがかなり小さくなるし、
誰もポインタで参照しなければ、スタックの中身は移動させることが可能になるよ。
0062デフォルトの名無しさん
2006/05/15(月) 23:55:45俺は、嫌だが。
0063デフォルトの名無しさん
2006/05/16(火) 13:08:24フレームポインタや戻り番地とかしか置かないってのも良いような・・
ヒープはコンパクションしないっていう方針ならフレームポインタは
ロードし直さなくて良いし。
大き目のローカル変数は構造体(等)にしてスマートポインタで確保、
というのを自動的にやってくれるイメージ。
0064デフォルトの名無しさん
2006/05/16(火) 14:57:55スタックを詰め込んでいいわけで、メモリ空間を無駄に予約する必要がなくなる。
0065デフォルトの名無しさん
2006/05/17(水) 22:44:18破綻することぐらい想像できないのか...。
0066デフォルトの名無しさん
2006/05/17(水) 22:56:33で、副作用として実行保留が簡単に実現出来るから
クライアントとして作ったオブジェクトがサーバに簡単に変身出来ると
0067デフォルトの名無しさん
2006/05/18(木) 16:42:22想像できないね。
ヒープのオーバーヘッドでリソースを無駄に食うことはあっても、破綻はしないでしょ。
ヒープが穴だらけになってヤバくなるのはオブジェクトのサイズがとても大きい場合。
現状でスタックに積むような小さなオブジェクトなら、あいた穴がすぐに再利用されるから。
0068デフォルトの名無しさん
2006/05/18(木) 22:22:14と言いながら、
> ヒープが穴だらけになってヤバくなるのはオブジェクトのサイズがとて
> も大きい場合。
って、あふぉですか?
0069デフォルトの名無しさん
2006/05/19(金) 10:59:04まあでももともとスタックにとるようなものだから、寿命は短いのではあるまいか。
とすればメモリ/アドレス空間に余裕があればそのうち解消する・・・
というかヒープ/メモリ空間の穴空きに関して言えば、
現状のスレッド毎にアドレス範囲を設定してFIFOで使うというのよりは
マシじゃないだろうか(速度的には不利だけど)。
0070デフォルトの名無しさん
2006/05/19(金) 14:50:23「大き目」
「とても大きい」
その違いがわからないなんて。
ヒープが穴だらけになって、
メモリは余っているのに、連続したアドレス空間がない
という破綻した状態になるのは、
スタックには確保できないような巨大なオブジェクトの話ですよ。
100KBとか1MBを越えるような、そんなサイズの。
0071デフォルトの名無しさん
2006/05/19(金) 16:14:050072デフォルトの名無しさん
2006/05/19(金) 20:18:27> メモリは余っているのに、連続したアドレス空間がない
> という破綻した状態になるのは、
> スタックには確保できないような巨大なオブジェクトの話ですよ。
違うよ。
どんな大きな領域でも同じようなサイズなら破綻はしにくい。
「大き目」と「とても大きい」サイズが混在するから穴があいて破綻するんだよ。
まさか、そんなことも知らないの?
>>71
それが割り当てられるなら、普通にスタックとして割り当てておけばいいだけ。
そしたら、>>64 もこんなあふぉな考えは浮かばなかっただろうにね。(w
0073デフォルトの名無しさん
2006/05/19(金) 20:47:31ヒープに取る方式なら、最初はスレッド毎に確保した領域を使い、
一杯になれば別の領域を使うという手が使える
つまり、スタックサイズの見積もりがたたないという問題の解決になる
0074デフォルトの名無しさん
2006/05/19(金) 22:11:19よくわからんけどさ、小さめのモノはスタックに置こう、
スタックに置くのはヤバげな大きいのはヒープに置こう、
ってのは人間が普段やってることなわけで、
それを否定されると C/C++ ではマルチスレッドアプリ書けなくなるし・・・
0075デフォルトの名無しさん
2006/05/20(土) 04:10:46それは、いったい、いつの時代のヒープの話ですか?
普通のCのプログラムで、
色んなサイズのオブジェクトをヒープに置いて、
破綻したという話なんて聞いたことがないよ。
0076デフォルトの名無しさん
2006/05/20(土) 04:37:080077デフォルトの名無しさん
2006/05/20(土) 06:56:360078デフォルトの名無しさん
2006/05/20(土) 09:13:04それは、ヒープとる時にいろいろな処理ができるというだけのこと。
スタックとる時に余計な処理を入れていいなら、スタックでもいっぱい
になったら別の領域を取ることは可能。
性能が犠牲になるからやってないだけのこと。
0079デフォルトの名無しさん
2006/05/20(土) 09:32:43巨大なローカル変数を取る場合は先頭で自己チェックを入れて
オーバーしそうなら別の領域にSPを取って
新しいSPに古いSPを保存、
自分の帰り番地になる場所に短いSP復元コードへのアドレスを書き込んでから実行
RET命令で、その復元コードに飛んで領域を消去してから元のSPに返るという感じかな
でもそれなら、最初から巨大なローカル変数はヒープに取ればいい事だな
0080デフォルトの名無しさん
2006/05/22(月) 13:17:46大き目のローカル変数をヒープに取るとマルチスレッド環境で破綻するので、
コンパクション無しのメモリ管理ではマルチスレッドアプリは書けない。
0081デフォルトの名無しさん
2006/05/24(水) 15:59:53話の流れを無視するなよ。
> 大き目のローカル変数をヒープに取るとマルチスレッド環境で破綻する
>>77
> コンパクション無しのメモリ管理ではマルチスレッドアプリは書けない。
>>77
>>76がキチガイなだけだから惑わされるな。
Windowsはヒープのコンパクションなんてやってくれないが、
マルチスレッドのプログラムで破綻するなんてことは、
まず普通はないから。
008281
2006/05/24(水) 16:00:53Windowsを前提とした話ではないからな。
■ このスレッドは過去ログ倉庫に格納されています