函数

时间:2018-04-13 17:55:23

标签: linux x86

我正在开发玩具编译器。我以前用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个字节。

1 个答案:

答案 0 :(得分:1)

RSP中减去某些内容不会导致任何问题,因为没有任何问题。它只是一个带有值的寄存器,它不会分配任何东西。但是当您使用CALL时,会访问RSP指向的内存,并且可能会发生问题。堆栈通常不是很大,所以你的问题“你有什么理由不能从堆栈中取出GB的内存”答案是“因为堆栈没有那么多的空间可供使用。” / p>

至于更快地在堆栈中分配大缓冲区并不是真的。在堆中分配和释放单个大块内存并不慢。在堆中有大量的分配和释放比在堆栈中更糟糕。因此,在这种情况下,在堆栈中执行此操作没有多大意义。