我通常用其他语言(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
iHat
和jHat
本身,但我我无法使用它们来访问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;
}
答案 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)尝试使用new
和delete
分配和清理动态内存。同样在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这是很多千兆字节而且它说数组太大了