C ++ 2D阵列分配内存以避免分段错误

时间:2016-12-19 20:14:13

标签: c++ memory-management multidimensional-array segmentation-fault

我通常用其他语言(R,Python和Java)编写代码,但最近开始使用C ++。我一直在hackerrank.com上解决问题,特别是我碰到了这个问题: https://www.hackerrank.com/challenges/variable-sized-arrays

在此问题出现之前,我从未遇到Segmentation Fault错误。我修改了代码并发现只有当我尝试从arr变量打印时才会出现错误。

我想知道是否有人可以帮助我,并且可能会提供有关确切错误的详细解释?

代码如下,但问题可能在于int arr[100000][100000] = {-1};printf("%d\n", arr[iHat][jHat]);,因为我可以printf iHatjHat本身,但我我无法使用它们来访问arr数组中的整数。

#include <iostream>

using namespace std;
    int main(){

        int n, q;

        /*
        *scan in:
        *n array entries
        *q quaries
        */

        int arr[100000][100000] = {-1}; //initialize an array, larger than 10^5

        scanf("%d %d\n", &n, &q); //n is size of array, q is # of quaries

        for (int i = 0; i < n; ++i){ //loop through lines of input to populate array
        int c, y = 0; //initialize to zero at the start of each line
            while((c = getchar()) != '\n'){ //readline
                if(c != ' '){ //pass spaces
                    arr[i][y] = c; //place integer into array
                    ++y;
                }
            }
        }

        for (int i = 0; i < q; ++i){
            int iHat, jHat = 0;
            scanf("%d %d\n", &iHat, &jHat); //scan for coordinates
            printf("%d\n", arr[iHat][jHat]); //Segmentation fault occurs here, why?
        }
        return 0;
    }

更新

这个问题主要关注内存管理,特别是指针的使用。导致无分段错误的功能解决方案如下:

#include <iostream>

using namespace std;
int main(){
    int n, q;
    /*
    *scan in:
    *n array entries
    *q quaries
    * format: %d %d
    */

    scanf("%d %d\n", &n, &q);//n is size of array of arrays, q is # of quaries

    int **arr = new int *[n]; //int** arr is a pointer of pointers of size n   

    for (int i = 0; i < n; ++i){//loop through lines of input to populate array  
        int k; //Always initialize variables in the narrowest scope possible!
        scanf("%d", &k);//grab k, the number of ints in the line
        arr[i] = new int[k];//create a 2nd dimension at entry i of size k
        for (int j = 0; j < k; ++j){
            scanf("%d", &arr[i][j]);//populate array
        }
    }

    for (int i = 0; i < q; ++i){
        int iHat, jHat = 0;
        scanf("%d %d\n", &iHat, &jHat); //scan for query coordinates
        printf("%d\n", arr[iHat][jHat]); //print results of query
    }

return 0;
}

4 个答案:

答案 0 :(得分:1)

那是40 GB!

即使机器中有这么多RAM,也肯定不会将其分配为堆栈空间。

如果你拥有那么多记忆,你可以在arr之前将main移动到全球区域。这样它就不会出现在堆栈中。

如果您没有40 GB可用,则可能需要重新考虑该解决方案。 :-)也许在较小的部分进行计算?

答案 1 :(得分:1)

以下是一些想法

1)您正尝试在堆栈上分配100,000 x 100,000字节,等于10,000,000,000字节(~10GB)。在32位Linux上,默认堆栈大小约为8MB。即使堆栈大小较大,也不会达到10GB。

2)您正在进行的练习的名称是&#34; Variable Sized Array&#34;您输入的行int arr[100000][100000]是固定大小的数组。您应该使用关键字new来动态创建数组。

3)分段错误错误的原因是因为您的print语句试图访问允许堆栈大小的虚拟内存空间之外的内存。

[建议]

1)尝试使用newdelete分配和清理动态内存。同样在C ++中,分配和删除数组的方式与单个数据结构不同。

干杯

答案 2 :(得分:1)

C ++使您可以控制要分配内存的位置。在您的情况下,您发现的是您在堆栈上分配了一个超出堆栈大小的array-of-array-int。在某些时候,您可以访问位于堆栈边界之外的这些元素之一以及程序,这会导致称为分段错误的访问冲突。

由于您提到了C ++的新手,因此有助于理解这3个内存区域以及如何将它们用于您的案例:

堆栈内存 - 临时变量自动使用的空间,无需显式请求。如果超过堆栈大小,您将看到未定义的行为。

int main() {
  int arr[100000][100000];
}

堆内存 - 用于在使用运算符“new”显式请求时动态分配空间的空间。如果请求的内存大小超过可用内存大小,将抛出“std :: bad_alloc”异常。

 int main() {

    int **arr = new int *[100000];

    for (std::size_t i = 0; i < 100000; ++i) {
       arr[i] = new int[100000];
     }
  }

静态内存 - 在主运行之前为静态对象分配的空间。如果数组维度太大,您将收到编译器错误。

  int arr[100000][100000];

  int main() {
    ...
  }

答案 3 :(得分:0)

你正试图这样做吗?

#include <iostream>

using namespace std;
int main(){

int n, q;
const int length = 100;

int arr[length][length] = { -1 }; 
cout << "Enter length of 2d array" << endl;
cin>>n>>q; 

cout << "Fill the array" << endl;
for (int i = 0; i < n; ++i) { 

    for(int y=0;y<q;y++){
        int f;
        cin >> f;
        arr[i][y]=f;            
        }
}


    int iHat;
    int jHat;
    cout << "Enter coordinates" << endl;
    cin>>iHat>>jHat; 

    cout<<arr[iHat][jHat]; 

    return 0;

}

P.S我减少了数组大小,因为100000 x 100000这是很多千兆字节而且它说数组太大了