如何修复堆栈溢出错误?

时间:2017-11-12 07:51:35

标签: c stack-overflow

所以,我正在制作这个节目,让人们知道连续的子阵列的数量,其总和等于某个值。

我已编写代码,但当我尝试在vcexpress 2010中运行此代码时,它会说出这些错误

  

测试9.exe中0x010018e7处的未处理异常:0xC00000FD:堆栈溢出。

我试图在本网站和其他网站上搜索解决方案,但我似乎无法找到任何可以帮助我修复此代码中的错误的解决方案(他们正在使用递归,而我是'我不是。

如果您愿意解释导致我的代码中出现此错误的原因以及如何解决此错误,我将非常感激。任何帮助,将不胜感激。谢谢。

这是我的代码:

#include <stdio.h>

int main ()
{
    int n,k,a=0,t=0;
    unsigned long int i[1000000];
    int v1,v2=0,v3;

    scanf("%d %d",&n,&k);

    for(v3=0;v3<n;v3++)
    {
    scanf("%d",&i[v3]);
    }

    do
    {
        for(v1=v2;v1<n;v1++)
        {
            t=i[v1]+t;
            if(t==k)
            {
                a++;
                break;
            }
        }
        t=0;
        v2++;
    }while(v2!=n);

    printf("%lu",a);


    return 0;

}

3 个答案:

答案 0 :(得分:3)

移动

     unsigned long int i[1000000];

main 之外,从而使其成为全局变量(不是automatic),或者更好,使用一些C dynamic heap allocation < /强>:

 // inside main
 unsigned long int *i = calloc(1000000, sizeof(unsigned long int));
 if (!i) { perror("calloc"); exit(EXIT_FAILURE); };
顺便说一句,对于这样的指针,我会使用(出于可读性的原因)除i之外的其他名称。在main即将结束时,您最好free(i);以避免memory leaks

此外,您可以在阅读n后移动这两行,并使用calloc(n, sizeof(unsigned long int))代替calloc(1000000, sizeof(unsigned long int));如果您的计算机和系统为此提供足够的资源,那么您可以处理超过一百万个元素的数组。

您的初始代码声明了一个自动变量,该变量进入call stack main的调用框架(其大小有限,通常为兆字节或其中几个)。在某些operating systems上,有一种方法可以增加该调用堆栈的大小(以特定于操作系统的方式)。 BTW每个thread都有自己的调用堆栈。

根据经验,您的C函数(包括main)应该避免使用大于几千字节的调用框架。使用GCC编译器,您可以调用with gcc -Wall -Wextra -Wframe-larger-than=1024 -g来获取有用的警告和调试信息。

阅读virtual address space wikipage。它有一个很好的图片值得多言。稍后,找到在您的操作系统上查询进程的虚拟地址空间的方法(在Linux上,使用cat /proc/$$/maps之类的proc(5)等等。在practice中,您的虚拟地址空间可能包含许多段(可能包含12个,有时甚至是数千个)。通常,程序(或您的C标准库)的dynamic linker或其他部分使用memory-mapped files。标准C堆(由malloc等管理)可以在几个 segments中进行组织。

如果您想了解有关虚拟地址空间的更多信息,请花时间阅读一本好书,例如:Operating systems, three easy pieces(可免费下载)。

如果要在某些process中查询虚拟地址空间的组织,则需要找到特定于操作系统的方法(在Linux上,对于pid 1234的进程,{{3来自流程内部的{}}或/proc/1234/maps

答案 1 :(得分:1)

记忆的布局与简单的4个部分(很久以前就已经完成)的区别更为明显。这个问题的答案可以通过这种方式推广 - 全局动态分配的内存空间的处理方式与系统局部变量的处理方式不同,因为局部变量的内存大小有限,动态分配的内存或全局变量不会像这样设置较低的约束。

在现代系统中,虚拟地址空间的概念就在那里。程序中的过程得到了一大块。现在,该部分内存负责保存所需的内存。

现在,对于动态分配等,进程可以请求更多内存,并且根据其他进程等,可以为新内存请求提供服务。对于动态或全局数组,没有限制过程(当然系统方面有 - 它不能请求所有内存)。这就是为什么动态分配或使用全局变量不会导致进程耗尽其分配的内存,这与它最初用于本地变量的自动生存期内存不同。

答案 2 :(得分:0)

基本上你可以检查堆栈大小 例如在Linux中:ulimit -s(Kbytes) 然后决定如何操纵你的代码。 作为一个概念,我永远不会在堆栈上分配大块内存,因为除非你确切知道函数调用的深度和堆栈的使用,否则在运行时很难控制堆栈上预先分配的内存