簡體   English   中英

C++:是什么導致了這個堆棧粉碎錯誤?

[英]C++: What is causing this stack smashing error?

免責聲明:我對 C++ 的了解有限,因為我從一所不教授 C++ 的大學轉到另一所教授唯一語言的大學。

我正在嘗試在 54x54 的格子中為隨機生成的 2D 集群實現盒子計數方法。

其中一個要求是我們使用一維數組來表示二維方格,因此需要進行轉換以將 x 和 y 值(分別為列和行)與數組的實際位置相關聯。 轉換為“i = x + y*N”,其中 N 是方格的邊長(在本例中為 54),i 是數組的 position。

簡單地說,box-counting 方法涉及將網格分成逐漸變小的大方塊,並計算每個實例中有多少包含集群。 該代碼的工作方式應該適用於較小的格子尺寸,至少是我可以驗證的那些(出於顯而易見的原因,我什至無法手動驗證 10x10 格子)。 但是,當我運行它時,盒子大小一直到 1/37,並給我一個“檢測到堆棧粉碎”錯誤。

據我了解,該錯誤可能與數組大小有關,但我檢查了訪問 arrays 的點,並確保它們在數組的實際尺寸范圍內。

function "boxTransform(int grid[], int NNew, int div)" 中的“for”是導致該錯誤的原因,但我添加了我認為與之相關的其他函數。 代碼的 rest 只是定義一個格子並隔離聚合,然后將其傳遞給 boxCounting(int grid[]),並創建一個.dat 文件。 那些工作正常。

為了將較大的數組“擬合”到較小的數組中,我將每個坐標 (x, y) 除以大數組與小數組上的正方形的比率。 這就是我的老師解釋它的方式,並且如前所述,它適用於較小的數組大小。

編輯:感謝 VTT 的評論,我回去檢查數組索引是否超出了代碼本身的范圍。 確實如此,這很可能是問題的根源。

編輯#2:這確實是問題的根源。 較小的晶格尺寸沒有出現計算中的輕微錯誤(或者我只是錯過了它)。

//grid[] is an array containing the cluster
//that I want to analyze.
void boxCounting(int grid[]) {
    //N is a global constant; it's the length of the
    //side of the square lattice that's being analyzed.
    //NNew is the side of the larger squares. It will
    //be increased until it reaches N
    for (int NNew = 1; N - NNew > 0; NNew++) {
        int div = N/NNew;
        boxTransform(grid, NNew, div);
    }
}

void boxTransform(int grid[], int NNew, int div) {
    int gridNew[NNew*NNew];
    //Here the array elements are set to zero, which
    //I understand C++ cannot do natively
    for (int i = 0; i < NNew*NNew; i++) {
        gridNew[i] = 0;
    }
    for (int row = 0; row < N; row++) {
        for (int col = 0; col < N; col++) {
            if (grid[col + row*N] == 1) {
                //This is where the error occurs. The idea here is
                //that if a square on the initial grid is occupied,
                //the corresponding square on the new grid will have
                //its value increased by 1, so I can later check
                //how many squares on the larger grid are occupied
                gridNew[col/div + (row/div)*NNew]++;
            }
        }
    }
    int boxes = countBox(gridNew, NNew);
    //Creates a .dat file with the relevant values
    printResult(boxes, NNew);
}

int countBox(int grid[], int NNew) {
    int boxes = 0;
    //Any array values that weren't touched remain at zero,
    //so I just have to check that it's greater than zero
    //to know if the square is occupied or not
    for(int i = 0; i < NNew*NNew; i++) {
        if(grid[i] > 0) boxes++;
    }
    return boxes;
}

不幸的是,這些信息不足以為您找到確切的問題,但我會盡力提供幫助。

您應該使用動態數組而不是您正在使用的固定大小 arrays 的原因有多種,除非您的練習需要它。 如果您一直在學習其他語言,您可能會認為固定數組已經足夠好,但在 C++ 中它比在大多數語言中危險得多。

  1. int gridNew[NNew*NNew]; 您應該知道,根據 C++ 標准,這是無效的,只有 GCC 編譯器使其工作。 在 C++ 中,您始終必須在編譯時知道固定 arrays 的大小。 這意味着您不能使用變量來聲明數組。

  2. 您不斷更新全局變量以跟蹤數組的大小,這使您的代碼非常難以閱讀。 您這樣做可能是因為您知道一旦將數組傳遞給 function,就無法查詢數組的大小。

對於這兩個問題,動態數組都是完美的解決方案。 C++ 中的標准動態數組實現是 std::vector: https://en.cppreference.com/w/cpp/container/vector

創建向量時,您可以定義它的大小,也可以使用size()成員 function 查詢向量的長度。

更好的是:您可以使用at() function 而不是方括號 ( [] ) 來獲取具有索引的元素,該索引會為您進行邊界檢查,如果您提供的索引超出范圍,則會引發異常,這有助於很多來定位這些類型的錯誤。 因為在 C++ 中,如果您只是提供一個數組中不存在的索引,則可能是您的問題的未定義行為。

我不想再寫向量的任何特性,因為很容易找到關於如何做這些事情的示例,我只是想幫助你從哪里開始。

VTT 在他的評論中是正確的。 將大數組放入較小數組的轉換存在一個小問題,導致索引 go 超出范圍。 當我應該把它放在實際代碼中時,我只在筆和紙上檢查了它,這就是我沒有注意到它的原因。 由於他沒有將其發布為答案,因此我代表他這樣做。

int gridNew[NNew*NNew]; 有點像紅鯡魚,但我很欣賞這個教訓,並且將來在 C++ 中編碼時會考慮到這一點。

暫無
暫無

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

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