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



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

在这个问题之前,我从来没有遇到过Segmentation Fault错误。我已经修改了代码,发现错误仅在我尝试从arr变量打印时才会发生。

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

代码如下,但问题可能出在int arr[100000][100000] = {-1};printf("%dn", arr[iHat][jHat]);上,因为我可以同时printfiHatjHat,但我无法使用它们来访问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 %dn", &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 %dn", &iHat, &jHat); //scan for coordinates
printf("%dn", 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 %dn", &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 %dn", &iHat, &jHat); //scan for query coordinates
printf("%dn", arr[iHat][jHat]); //print results of query
}
return 0;
}

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

既然你提到你是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() {
...
}

那是 40 GB!

即使您在机器中有那么多 RAM,它肯定不会分配为堆栈空间。

如果您确实有那么多内存,则可以在main之前将arr移动到全局区域。这样它就不会在堆栈上。

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

这里有一些想法

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

2)您正在处理的练习的名称是"可变大小数组"您输入的行,int arr[100000][100000]是一个固定大小的数组。 您应该使用关键字new来动态创建数组。

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

[建议]

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

干杯

你想这样做吗?

#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 i 减小了阵列大小,因为 100000 x 100000 这是很多千兆字节,它说数组太大了

相关内容

  • 没有找到相关文章