このコードは、スタックに割り当てられた変数への無効な参照を返しますか? または何:
void *f(size_t sz) {
return alloca(sz);
}
それとも、alloca の実装/コンパイラ サポートによって処理される特殊なケースf(alloca(size), alloca(size))
ですか?
このコードは、スタックに割り当てられた変数への無効な参照を返しますか? または何:
void *f(size_t sz) {
return alloca(sz);
}
それとも、alloca の実装/コンパイラ サポートによって処理される特殊なケースf(alloca(size), alloca(size))
ですか?
alloca
のスタックフレームにスペースを割り当てますf
。関数が戻ると、それを使って有用なことは何もできなくなります(もう「予約」されていません)。
alloca()関数は、呼び出し元のスタックフレームにサイズバイトのスペースを割り当てます。この一時スペースは、alloca()を呼び出した関数が呼び出し元に戻ると自動的に解放されます。
Linuxのマニュアルページによると:
この
alloca()
関数は、呼び出し元のスタックフレームにスペースを割り当て、割り当てられたブロックへのポインターを返します。この一時スペースは、呼び出された関数が戻るときに自動的に解放さalloca()
れます。
つまり、によって返されたメモリにアクセスしようとすると、戻ったf()
ときに解放されるため、未定義の動作が発生しf()
ます。
はい、コードは無効なポインタを返します。alloca
呼び出しを関数にラップすることはできません。ラップする必要がある場合alloca
は、マクロラッパーに制限されます。
他の人が言っているように、それは解放されるでしょう、そして私はあなたがどのように振る舞いを変えることができるか本当にわかりません。alloca
がamd-64でどのようにコンパイルされるかを見ると:
pushq %rbp
movq %rsp, %rbp
subq $144, %rsp
movq %rsp, %rax
addq $15, %rax
shrq $4, %rax
salq $4, %rax
leave
ret
分かりますか
1)Allocaは実際には関数呼び出しではありません(あなたが言ったように、スタックを別の方法で処理する必要があるためです!)
2)スタックポインタに対してallocaが行うことはすべて、rbp
上書き時に関数の最後で壊れるだけです。rsp
それで、あなたはあなたが尋ねる振る舞いを(アセンブリを書かずに)得ることができますか?それは難しい質問で、私にはわかりませんが、おそらくそうではないようです。
私は alloca を自分で使用したことはありませんが、ここで「インラインの問題」について読み ました。
「最も記憶に残るバグの 1 つ...」という回答は非常に興味深いものです。
したがって、関数がスコープ外になるとメモリが確実に解放されるというわけではありません。