我是否正确地认为,在以下代码段中,自动变量x
和y
将在while循环的每次传递中重新分配到堆栈上并且永不释放,最终导致堆栈溢出?在从内部z
循环的范围内激发后,每次传递还会有10次重新分配while
吗?
如果此片段放在工作线程中,则在线程服务其时间分配后,是否会保存堆栈以重新进入,即x
和y
将永远< / em>被解除分配?
while (1)
{
int x = 0;
int *y = &x;
while (x < 10)
{
int z = 0;
++x;
}
}
答案 0 :(得分:1)
最终导致堆栈溢出?
没有。当超出范围时,自动变量将被清除。如果你愿意,你可以想到堆栈在每次迭代开始时都在增长,然后在每次迭代结束时收缩。 (在实践中是否发生这种情况是另一回事......)
如果此片段放在工作线程中,那么在线程服务其时间分配后是否会保存堆栈以便重新进入,即x和y是否永远不会被释放?
在一个正常运行的系统中,每个线程都有自己的堆栈,当该线程终止时,该堆栈会被清除。
答案 1 :(得分:1)
不,没问题。自动变量每次都可以轻松地重复使用相同的空间。请记住,自动变量的生命周期在块结束时结束,因此它们的寿命永远不会超过一次迭代。
(事实上,你需要很多 more 代码来构造一些东西,其中每次迭代使用不同的内存位置 - 你必须保留一个额外的计数器每次都计算一个偏移量!)
答案 2 :(得分:1)
x
,y
和z
的空间将在每轮循环中重复使用。任何地方都没有动态分配或解除分配。
通常,本地自动变量的空间将在函数入口处的堆栈上分配,并在函数结束时释放。
答案 3 :(得分:1)
对于这种情况,您可以使用
轻松检查编译器正在执行的操作 gcc -g -c yourfile.c
然后用
查看生成的程序集 objdump -d -M intel -S yourfile.o
:
00000000 <main>:
int main() {
0: 55 push ebp
1: 89 e5 mov ebp,esp
3: 83 ec 10 sub esp,0x10
啊!这是堆栈指针被修改的地方。请注意,对于函数的其余部分,它是独立的:堆栈不会增长。
while (1)
{
int x = 0;
6: c7 45 f4 00 00 00 00 mov DWORD PTR [ebp-0xc],0x0
我们将x
放在[ebp-0xc]
...
int *y = &x;
d: 8d 45 f4 lea eax,[ebp-0xc]
10: 89 45 f8 mov DWORD PTR [ebp-0x8],eax
...和y
[ebp-0x8]
。
while (x < 10)
13: eb 10 jmp 25 <main+0x25>
{
int z = 0;
15: c7 45 fc 00 00 00 00 mov DWORD PTR [ebp-0x4],0x0
z
始终位于[ebp-0x4]
!
++x;
1c: 8b 45 f4 mov eax,DWORD PTR [ebp-0xc]
1f: 83 c0 01 add eax,0x1
22: 89 45 f4 mov DWORD PTR [ebp-0xc],eax
25: 8b 45 f4 mov eax,DWORD PTR [ebp-0xc]
x
仍在[ebp-0xc]
!
28: 83 f8 09 cmp eax,0x9
2b: 7e e8 jle 15 <main+0x15>
2d: eb d7 jmp 6 <main+0x6>