我正在开发玩具编译器。我以前用malloc分配所有内存,但由于我从不调用free,我认为在堆栈上分配GB左右然后慢慢使用该缓冲区就足够了(并且更快)。
但是......现在我在发生任何有趣的事情之前就已经过了一段时间。它发生在大约30%的测试用例中(所有测试用例在本节中都是相同的)。粘贴GDB:
(gdb) disas
Dump of assembler code for function main:
0x0000000000400bf1 <+0>: push rbp
0x0000000000400bf2 <+1>: mov rbp,rsp
0x0000000000400bf5 <+4>: mov QWORD PTR [rip+0x2014a4],rsp # 0x6020a0
0x0000000000400bfc <+11>: sub rsp,0x7735940
0x0000000000400c03 <+18>: sub rsp,0x7735940
0x0000000000400c0a <+25>: sub rsp,0x7735940
0x0000000000400c11 <+32>: sub rsp,0x7735940
=> 0x0000000000400c18 <+39>: call 0x400fec <new_Main>
0x0000000000400c1d <+44>: mov r15,rax
0x0000000000400c20 <+47>: mov rax,r15
0x0000000000400c23 <+50>: add rax,0x20
0x0000000000400c27 <+54>: mov rax,QWORD PTR [rax]
0x0000000000400c2a <+57>: add rax,0x48
0x0000000000400c2e <+61>: mov rax,QWORD PTR [rax]
0x0000000000400c31 <+64>: call rax
0x0000000000400c33 <+66>: mov rax,0x0
0x0000000000400c3a <+73>: mov rsp,rbp
0x0000000000400c3d <+76>: pop rbp
0x0000000000400c3e <+77>: ret
我最初做了一个大的“sub rsp,0x ......”而且我认为将其分解会有所帮助(它没有 - 程序在任何一种情况下都会崩溃)。在这种情况下,总数应为500MB。
让我感到困惑的是为什么它在“call&lt;&gt;”上失败了而不是其中一个潜艇。为什么它只是在某些时候失败而不是永远或永远失败。
披露:这是一个学校项目,但是就x86的一般问题寻求帮助并不违反任何规则。
更新:根据@ swift的评论,我设置了ulimit -s unlimited ...现在它是随机的段错误吗?这似乎是随机的。它并没有接近使用整个500 MB缓冲区。它总共只分配了大约400个字节。
答案 0 :(得分:1)
从RSP
中减去某些内容不会导致任何问题,因为没有任何问题。它只是一个带有值的寄存器,它不会分配任何东西。但是当您使用CALL
时,会访问RSP
指向的内存,并且可能会发生问题。堆栈通常不是很大,所以你的问题“你有什么理由不能从堆栈中取出GB的内存”答案是“因为堆栈没有那么多的空间可供使用。” / p>
至于更快地在堆栈中分配大缓冲区并不是真的。在堆中分配和释放单个大块内存并不慢。在堆中有大量的分配和释放比在堆栈中更糟糕。因此,在这种情况下,在堆栈中执行此操作没有多大意义。