簡體   English   中英

C ++ 2D陣列分配內存可避免分段錯誤

[英]C++ 2D Array Allocating Memory to Avoid 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]); 因為我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 %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;
}

那是40 GB!

即使計算機中有那么多RAM,也肯定不會將其分配為堆棧空間。

如果確實有那么多內存,則可以將arr移到main之前的全局區域。 這樣,它將不會出現在堆棧中。

如果您沒有40+ GB的可用空間,則可能必須重新考慮該解決方案。 :-)也許在較小的細分中進行計算?

這里有一些想法

1)您正在嘗試分配100,000 x 100,000字節,這等於堆棧上的10,000,000,000字節(〜10GB)。 在32位linux上,默認堆棧大小約為8MB。 即使堆棧較大,也不會是10GB。

2)您正在執行的練習的名稱是“可變大小數組”。您輸入的行int arr[100000][100000]是固定大小的數組。 您應該使用關鍵字new來動態創建數組。

3)出現Segmentation Fault錯誤的原因是因為您的打印語句試圖訪問允許堆棧大小的虛擬內存空間之外的內存。

[建議]

1)嘗試做一些練習,在其中使用newdelete分配和清理動態內存。 同樣,在C ++中,分配和刪除數組的方式與單個數據結構不同。

干杯

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() {
    ...
  }

您是否正在嘗試這樣做?

#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;

}

PS i減小了陣列大小,因為100000 x 100000,這是很大的千兆字節,它表示陣列太大

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM