编辑在你兴奋之前,最后看到重要的编辑,如果你仍然好奇,这些被报道为:


我一直在尝试一段代码,并惊讶地发现我没有得到堆栈溢出。 试图简化我甚至得到的东西:

#include <stdio.h>

int main()
{
    int i;

    /* 1,500,000,000 x 4 bytes = 6,000,000,000 bytes = 6GB */
    int size = 1500000000;
    int arr[size];
    for (i = 0; i < size; i++) {
        arr[i] = 1;
    }
    printf("first: %d\n", arr[0]);
    printf("last:  %d\n", arr[size - 1]);

    return 0;
}

这使我怀疑我甚至不知道内存管理的基础知识。 我在想arr[size]应该在堆栈上轻松分配并且很容易溢出,而是它使用我所有的内存并交换并成功完成。 我错过了什么?

笔记

  • 我在64位ubuntu 12.04上运行
  • 我尝试过使用gccclang版本:

     gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3 Ubuntu clang version 3.0-6ubuntu3 (tags/RELEASE_30/final) (based on LLVM 3.0) 
  • 我关闭了优化( -O0

  • 运行ulimit -a我得到:

     core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 29569 max locked memory (kbytes, -l) 64 max memory size (kbytes, -m) unlimited open files (-n) 1024 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 8192 cpu time (seconds, -t) unlimited max user processes (-u) 29569 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited 
  • 我有4GB的RAM和大约相同的交换量


(gdb) disassemble main
Dump of assembler code for function main:
   0x00000000004004f4 <+0>:     push   %rbp
   0x00000000004004f5 <+1>:     mov    %rsp,%rbp
   0x00000000004004f8 <+4>:     push   %rbx
   0x00000000004004f9 <+5>:     sub    $0x38,%rsp
   0x00000000004004fd <+9>:     mov    %rsp,%rax
   0x0000000000400500 <+12>:    mov    %rax,%rbx
   0x0000000000400503 <+15>:    movl   $0x59682f00,-0x14(%rbp)
   0x000000000040050a <+22>:    mov    -0x14(%rbp),%eax
   0x000000000040050d <+25>:    movslq %eax,%rdx
   0x0000000000400510 <+28>:    sub    $0x1,%rdx
   0x0000000000400514 <+32>:    mov    %rdx,-0x28(%rbp)
   0x0000000000400518 <+36>:    cltq
   0x000000000040051a <+38>:    shl    $0x2,%rax
   0x000000000040051e <+42>:    lea    0xf(%rax),%rdx
   0x0000000000400522 <+46>:    mov    $0x10,%eax
   0x0000000000400527 <+51>:    sub    $0x1,%rax
   0x000000000040052b <+55>:    add    %rdx,%rax
   0x000000000040052e <+58>:    movq   $0x10,-0x38(%rbp)
   0x0000000000400536 <+66>:    mov    $0x0,%edx
   0x000000000040053b <+71>:    divq   -0x38(%rbp)
   0x000000000040053f <+75>:    imul   $0x10,%rax,%rax
   0x0000000000400543 <+79>:    sub    %rax,%rsp
   0x0000000000400546 <+82>:    mov    %rsp,%rax
   0x0000000000400549 <+85>:    add    $0xf,%rax
   0x000000000040054d <+89>:    shr    $0x4,%rax
   0x0000000000400551 <+93>:    shl    $0x4,%rax
   0x0000000000400555 <+97>:    mov    %rax,-0x20(%rbp)
   0x0000000000400559 <+101>:   movl   $0x0,-0x18(%rbp)
   0x0000000000400560 <+108>:   jmp    0x400577 <main+131>
   0x0000000000400562 <+110>:   mov    -0x20(%rbp),%rax
   0x0000000000400566 <+114>:   mov    -0x18(%rbp),%edx
   0x0000000000400569 <+117>:   movslq %edx,%rdx
   0x000000000040056c <+120>:   movl   $0x1,(%rax,%rdx,4)
   0x0000000000400573 <+127>:   addl   $0x1,-0x18(%rbp)
   0x0000000000400577 <+131>:   mov    -0x18(%rbp),%eax
   0x000000000040057a <+134>:   cmp    -0x14(%rbp),%eax
   0x000000000040057d <+137>:   jl     0x400562 <main+110>
   0x000000000040057f <+139>:   mov    -0x20(%rbp),%rax
   0x0000000000400583 <+143>:   mov    (%rax),%edx
   0x0000000000400585 <+145>:   mov    $0x4006bc,%eax
   0x000000000040058a <+150>:   mov    %edx,%esi
   0x000000000040058c <+152>:   mov    %rax,%rdi
   0x000000000040058f <+155>:   mov    $0x0,%eax
---Type <return> to continue, or q <return> to quit---
   0x0000000000400594 <+160>:   callq  0x4003f0 <printf@plt>
   0x0000000000400599 <+165>:   mov    -0x14(%rbp),%eax
   0x000000000040059c <+168>:   lea    -0x1(%rax),%edx
   0x000000000040059f <+171>:   mov    -0x20(%rbp),%rax
   0x00000000004005a3 <+175>:   movslq %edx,%rdx
   0x00000000004005a6 <+178>:   mov    (%rax,%rdx,4),%edx
   0x00000000004005a9 <+181>:   mov    $0x4006c7,%eax
   0x00000000004005ae <+186>:   mov    %edx,%esi
   0x00000000004005b0 <+188>:   mov    %rax,%rdi
   0x00000000004005b3 <+191>:   mov    $0x0,%eax
   0x00000000004005b8 <+196>:   callq  0x4003f0 <printf@plt>
   0x00000000004005bd <+201>:   mov    $0x0,%eax
   0x00000000004005c2 <+206>:   mov    %rbx,%rsp
   0x00000000004005c5 <+209>:   mov    -0x8(%rbp),%rbx
   0x00000000004005c9 <+213>:   leaveq
   0x00000000004005ca <+214>:   retq
End of assembler dump.

$ pmap 2840
2840:   ./a.out
0000000000400000      4K r-x--  /home/gokce/play/a.out
0000000000600000      4K r----  /home/gokce/play/a.out
0000000000601000      4K rw---  /home/gokce/play/a.out
00002b572d7be000    136K r-x--  /lib/x86_64-linux-gnu/ld-2.15.so
00002b572d7e0000      8K rw---    [ anon ]
00002b572d9e0000      4K r----  /lib/x86_64-linux-gnu/ld-2.15.so
00002b572d9e1000      8K rw---  /lib/x86_64-linux-gnu/ld-2.15.so
00002b572d9e3000   1748K r-x--  /lib/x86_64-linux-gnu/libc-2.15.so
00002b572db98000   2044K -----  /lib/x86_64-linux-gnu/libc-2.15.so
00002b572dd97000     16K r----  /lib/x86_64-linux-gnu/libc-2.15.so
00002b572dd9b000      8K rw---  /lib/x86_64-linux-gnu/libc-2.15.so
00002b572dd9d000     28K rw---    [ anon ]
00007ffe080a2000 5859388K rw---    [ stack ]
00007fff6dbfc000      4K r-x--    [ anon ]
ffffffffff600000      4K r-x--    [ anon ]
 total          5863408K

重要编辑

我用的是一个小手写的makefile:

build:
        gcc foo.c -Wall -Wextra -g

run:
        ./a.out

.SILENT:

使用我的常用编辑器镜头来运行程序,我现在意识到它在某种程度上是相关的。 当我从控制台运行时,我得到了段错误:

./a.out

但不是我跑的时候:

make run

那有什么关系?

重要的编辑2

当我尝试在make run运行ulimit -s时:

build:
        gcc foo.c -Wall -Wextra -g

run:
        ulimit -s

.SILENT:

它给:

make: ulimit: Command not found
make: *** [run] Error 127

然后当我最后添加额外的#时,我意识到它会发生变化:(不是注释字符吗?)

build:
        gcc foo.c -Wall -Wextra -g

run:
        ulimit -s #

.SILENT:

我明白了:

unlimited

我还检查了我的bash别名,没有make which make赋予/usr/bin/makefile /usr/bin/make给出:

/usr/bin/make: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically 
linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0x1d76b881b71091d
37e6653d7c8b8e19a2a414591, stripped

===============>>#1 票数:4 已采纳

正如您所期望的那样, arr显然已经被分配到堆栈中。 pmap输出,堆栈显然增长到接近6GB:

00007ffe080a2000 5859388K rw---    [ stack ]

因此,问题不在于您的程序或编译器。 问题是为什么ulimit -s 8192显然没有得到执行。

根据你对我的各种问题的回答,很明显, ulimit -s设置不会通过make run传播到你的程序。 这对我来说似乎很奇怪。

如果我在你的位置,我会通过系统的limits.conf以及共享和用户的bash启动文件来查看我是否能发现任何相关内容。

===============>>#2 票数:0

没有验证它,但恕我直言,这是正在发生的事情:

int size = 1500000000;

你在这里得到一个溢出 - 这个数字对于int来说太大了。 变量“size”的实际值将低得多。 您的编译器实际上应该警告您这一点。 再一次,我没有验证它,因为我太懒了。 尝试这个:

#define SIZE 1500000000ULL
int arr[SIZE];

而且,当然,“i <SIZE”条件也需要更正 - 我是int,所以条件总是正确的(同样,编译器也应该警告你这一点)。 祝好运。

  ask by none translate from so

未解决问题?本站智能推荐:

6回复

什么导致堆栈溢出?

您可能认为这是一个巧合,我的问题的主题类似于论坛的名称,但我实际上是通过谷歌搜索“堆栈溢出”一词来到这里。 我使用OPNET网络模拟器,我使用C编程。我认为我遇到了大数组大小的问题。 看来我正在达到某种内存分配限制。 它可能与OPNET,Windows,我的笔记本电脑内存或最有可能的C
4回复

分段错误和堆栈溢出之间有什么区别?

例如,当我们调用一个递归函数时,后续调用将存储在堆栈中。 但是,由于错误(如果无限进行),该错误是“分段错误”(如GCC所示)。 难道不是“堆栈溢出”吗? 两者之间的基本区别是什么? 顺便说一句,一种解释将比维基百科链接更有用(通过该链接,但对特定查询没有答案)。
1回复

当内存非常低时,线程内的srand()导致堆栈溢出

这是在Windows XP的VisualStudio中用C / C ++开发的多线程应用程序。 用户报告说它崩溃并显示错误“ Stack Overflow” 调试后,发现在计算机内存不足时,在导致“堆栈溢出”的线程之一中调用srand() 。 令人惊讶的是,在调用srand()的线
3回复

Haskell堆栈溢出

我正在编写一种遗传算法来生成字符串“ helloworld”。 但是当n为10,000或更大时,evolve函数会产生堆栈溢出。 species pool = 8 ,由8个基因组成的库将复制到8个组中。 每组发生突变,并选择每组的最适体进行进一步进化(返回8个基因)。 的Git
1回复

查找堆栈缓冲区溢出

我已经阅读了有关Stack Buffer Overflows和Heap溢出的5篇论文/文章和2个视频。 我编写了一个容易被溢出和利用的程序,在端口7777上运行了一个易受攻击,溢出和利用的服务器。 但我不明白的是如何在Windows(或其他操作系统)或软件中查找漏洞。 我正在使用gcc和g
2回复

访问作为参数传递的字符串会导致堆栈缓冲区溢出

我正在uni学习C,正在尝试访问传递到函数中的字符串(二进制数的字符串表示形式)以将其转换为该字符串的整数表示形式。 例如。 "011"应返回3 。 字符串是反向输入的比特流中的前3位。 fromBinaryToInt函数为: 我得到的后续错误是: == 21
2回复

奇怪的堆栈溢出?

我遇到了一个奇怪的情况,它将一个指针传递给一个结构,该结构在struct {}定义中定义了一个非常大的数组,一个大小为34MB的浮点数组。 简而言之,伪代码看起来像这样: 代码编译得很好,但是当我尝试运行它时,我会在{Read_Config_File()下面得到一个SIGSEGV。
3回复

捕获堆栈溢出

在C中捕获堆栈溢出的最佳方法是什么? 进一步来说: AC程序包含脚本语言的解释器。 脚本不受信任,可能包含无限的递归错误。 口译员必须能够抓住这些并顺利地继续下去。 (显然,这可以通过使用软件堆栈来部分处理,但是如果可以用C语言编写大量的库代码块,性能会大大提高;至少,这需
8回复

产生堆栈溢出

如何在GNU / Linux中创建堆栈溢出的条件?
7回复

线程堆栈溢出

在像我们创建任务的vxworks这样的RTO中,指定了stacksize。 我们可以在C中编写一个例程来检查堆栈是否溢出或者没有执行任务吗?