首页 > 解决方案 > 以下程序中的分段错误

问题描述

我试图解决非常基本的问题SPOJ CANDY 在提交以下解决方案时出现分段错误。但在 Visual Studio 中它工作正常。我还通过考虑大小(sum as long long int)来声明变量,因为它可能很大

1)是不是因为我在while循环中声明了数组;我是否应该在 while 循环之外声明该数组,以便对于每个测试用例它都使用相同的数组

2)每次循环运行(对于每个测试用例)都会创建新数组,是否会导致垃圾收集或编译器会在每个测试用例后自动释放内存(我知道动态内存分配在这种情况下我们必须释放显式内存)你能告诉我我应该在哪个范围内声明变量吗?

我有上述疑问,因为分段错误与内存访问有关。

   #include<iostream>
    using namespace std;



    int main(){

        while(1){
            int n;
            int arr[10001];
            cin>>n;
            if(n==-1)
                break;
            long long int sum=0;
            for(int i=0;i<n;i++){
                int temp;
                cin>>temp;
                sum+=temp;
                arr[i]=temp;

            }
             int mean=sum/n;
            if((sum%n)!=0){
                cout<<-1<<endl;
                continue;
                }
             int count1=0;
             for(int i=0;i<n;i++){
                if(arr[i]>mean){
                    count1+=(arr[i]-mean);

                }
             }
             cout<<count1<<endl;

        }

    }

标签: c++

解决方案


您的问题可能是由于int arr[10001]. 这很可能是一个 40kB 的分配。现在,“分配”是错误的词,因为它本质上只是arr通过执行类似int * arr = STACK_POINTER-40004.

不幸的是,默认情况下最大堆栈大小为 12 kB 是很常见的。这意味着操作系统将 12 kB 映射到内存并设置STACK_POINTER到该内存的顶部(假设堆栈向下增长)。

所以最终效果是您的arr指针现在指向已分配堆栈之外 - 指向未分配内存 - 并且第一次访问会引发分段错误。通常,您可以通过增加堆栈大小来解决此问题ulimit -s,但您无法控制所使用的判断平台。

你有两个选择:

  • 改用堆分配int *arr = new int[10001]。这不受初始堆栈大小的影响。在普通程序中,您应该注意清理它,但对于像这样的短程序,则没有必要。
  • 将声明int arr[10001]移到顶层。arr将指向一个称为 BSS 部分的区域,该区域最初为零。这也不受初始堆栈大小的影响。

推荐阅读