スレッドとスタックの動作を研究
#wip #スレッド #スタック #tips
データがいつスタックに積まれ、そしてスタックからデータが解放され、スタックポインタが動くのか
todo.iconこの挙動がまだ掴めてない。理解できてない。
スレッドごとに使えるスタックサイズの大きさってのは決まってて、それ以上の大きさのデータを確保しようとするとスタックオーバーフローが起きる
シンプルにめっちゃ大きいサイズのデータをスタックに確保する
code: rust
fn main() {
let main_array = 0u8; 9_000_000;
println!("メインスレッド: 配列のアドレス: {:p}", &main_array0);
}
基本的にメインスレッドのスタックサイズは8MBくらいなので、それ以上のサイズのメモリ空間を確保しようとするとスタックオーバーフローで落ちる。
合計で超えてももちろんダメ
code: rust
fn main() {
let main_array = 0u8; 5_000_000;
let sub = 0u8; 4_000_000;
println!("メインスレッド: 配列のアドレス: {:p}", &main_array0);
}
スタックから先に解放するように書いても無理。
code: rust
fn main() {
println!("開始");
{
let main_array = 0u8; 5_000_000;
println!("メインスレッド: 配列のアドレス: {:p}", &main_array0);
}
let sub = 0u8; 4_000_000;
println!("メインスレッド: 配列のアドレス: {:p}", &sub0);
}
おそらく、最適化とかで先にスタック確保されてる。
だから、実行前にstackoverflow起きる。開始も表示されない。
ちょっとこの挙動は素人すぎて理解できない。どうなってるんだろう。
q.icon この挙動にはまだ疑問が残ってるな。プログラムの低層は直感から離れてて難しいな。
どうやら完全に別々の関数に書いたらいける
code: rust
fn main() {
println!("開始");
alloc4mb();
alloc5mb();
}
fn alloc4mb() {
let _sub = 0u8; 4_000_000;
println!("サブスレッド: 配列のアドレス: {:p}", &_sub0);
}
fn alloc5mb() {
let _sub = 0u8; 5_000_000;
println!("サブスレッド: 配列のアドレス: {:p}", &_sub0);
}
4mbが解放されてすぐにスタックポインタが戻されてるっぽい。
その後に5mbを確保するからうまくいく。
前回との違いはなんだろうか。
q.icon スタックフレームとスタックポインタの動きの関係を理解しないとダメそう。