簡體   English   中英

堆棧粉碎檢測到 C++

[英]Stack smashing detected C++

我正在寫一個小程序。 我在我的 Windows 上構建工作。 我在我的 Ubuntu 上重寫了這個程序的精確副本。 但是在 Ubuntu 中,每次執行我的程序時都會出現堆棧粉碎錯誤。 在兩個操作系統中,我都使用 Codeblocks IDE。 這是我的代碼:

#include <stdio.h>


double max_elem(double a, double b)
{
    if (a <= b )
        return a;
    else return b;
}
double  min_elem(double a,double b)
{
    if (a >= b )
        return a;
    else return b;
}
double result (int pawn_v, int pawn_h, int knight_v, int knight_h)
{
    double result_array[7];
    for (int i=0; i<=7; i++)
        result_array[i] = 2;
    double a,b,c,d;
    pawn_h++;

    if (pawn_h>8)
        return 1;
    else if ((pawn_v == knight_v + 2) && (pawn_h == knight_h + 1))
        return -1;
    else if ((pawn_v == knight_v + 2) && (pawn_h == knight_h - 1))
        return -1;
    else if ((pawn_v == knight_v - 2) && (pawn_h == knight_h + 1))
        return -1;
    else if ((pawn_v == knight_v - 2) && (pawn_h == knight_h - 1))
        return -1;
    else if ((pawn_v == knight_v + 1) && (pawn_h == knight_h + 2))
        return -1;
    else if ((pawn_v == knight_v + 1) && (pawn_h == knight_h - 2))
        return -1;
    else if ((pawn_v == knight_v - 1) && (pawn_h == knight_h + 2))
        return -1;
    else if ((pawn_v == knight_v - 1) && (pawn_h == knight_h - 2))
        return -1;
    else if ((pawn_v == knight_v) && (pawn_h == knight_h))
        return (0.5f);
    else
    {

        result_array[0] = result(pawn_v, pawn_h, knight_v + 2, knight_h + 1);

        result_array[1] = result(pawn_v, pawn_h, knight_v + 2, knight_h - 1);

        result_array[2] = result(pawn_v, pawn_h, knight_v - 2, knight_h + 1);

        result_array[3] = result(pawn_v, pawn_h, knight_v - 2, knight_h - 1);

        result_array[4] = result(pawn_v, pawn_h, knight_v + 1, knight_h + 2);

        result_array[5] = result(pawn_v, pawn_h, knight_v - 1, knight_h + 2);

        result_array[6] = result(pawn_v, pawn_h, knight_v + 1, knight_h - 2);

        result_array[7] = result(pawn_v, pawn_h, knight_v - 1, knight_h - 2);

        a = max_elem(result_array[0],result_array[1]);
        b = max_elem(result_array[2],result_array[3]);
        c = max_elem(result_array[4],result_array[5]);
        d = max_elem(result_array[6],result_array[7]);
        return (max_elem(max_elem(a,b),max_elem(c,d)));
    }
}
int main()
{

    char knight_start, pawn_start;
    int knight_start_horizontal, pawn_start_horizontal, knight_start_vertical, pawn_start_vertical;

    scanf("%c%d%*c%c%d%*c", &pawn_start, &pawn_start_horizontal, &knight_start, &knight_start_horizontal);
    knight_start_vertical = int(knight_start)-96;
    pawn_start_vertical = int(pawn_start)-96;

    if (pawn_start_horizontal==2) {
        if (min_elem(result(pawn_start_vertical,pawn_start_horizontal,knight_start_vertical,knight_start_horizontal),result(pawn_start_vertical,pawn_start_horizontal+1,knight_start_vertical,knight_start_horizontal))==0.5)
            printf("%.1f", 0.5);
        else printf("%0.f",min_elem(result(pawn_start_vertical,pawn_start_horizontal,knight_start_vertical,knight_start_horizontal),result(pawn_start_vertical,pawn_start_horizontal+1,knight_start_vertical,knight_start_horizontal)));
    }
    else
    {
        if (result(pawn_start_vertical,pawn_start_horizontal,knight_start_vertical,knight_start_horizontal)==0.5)
            printf("%.1f",0.5);
        else printf("%.0f", result(pawn_start_vertical,pawn_start_horizontal,knight_start_vertical,knight_start_horizontal));
    }
    return 0;
}

我怎樣才能防止這個錯誤?

我在我的 Windows 上構建工作。 我在我的 Ubuntu 上重寫了這個程序的精確副本。 但是在 Ubuntu 中,每次執行我的程序時都會出現堆棧粉碎錯誤。

首先,僅說明操作系統的名稱是不夠的。 在任何這些系統上都有多個可用的編譯器 更不用說“Windows”理論上可以是從 Windows 1 到 Windows 10 的所有東西,“Ubuntu”也幾乎不是一個非常精確的定義。 並且編譯器具有不同的版本和不同調用選項的無限組合。

其次,如果“堆棧粉碎錯誤”是指分段錯誤,則程序也會“在 Windows 上”崩潰。 我剛剛在我的 Windows 7 64 位機器上使用/EHsc /Za在 MSVC 2013 上進行了嘗試。 在我使用或多或少的隨機輸入對其進行測試后,它崩潰了(我剛剛輸入了 12、2 和 2)。

我怎樣才能防止這個錯誤?

通過避免 C++ 所說的未定義行為 與某些其他語言相比,C++ 有時會在您出現嚴重的編程錯誤(例如嘗試訪問不應該訪問的內存)時將程序的行為留給編譯器或操作系統。 崩潰或看似隨機的崩潰是未定義行為的一種可能表現。

據我所知,您的代碼中有兩個未定義行為的實例。 請注意,第一個已經足以使整個程序無效。

 double result_array[7]; for (int i=0; i<=7; i++) result_array[i] = 2;

[7]表示這是一個有 7 個元素的數組,但這些元素的索引是 0、1、2、3、4、5、6。 在循環的最后一次迭代中, i為 7,因此您嘗試訪問result_array[7] 這是未定義的行為。

 d = max_elem(result_array[6],result_array[7]);

同樣, result_array[7]是未定義的行為。

現在,就您的main功能而言......

 char knight_start, pawn_start; int knight_start_horizontal, pawn_start_horizontal, knight_start_vertical, pawn_start_vertical; scanf("%c%d%*c%c%d%*c", &pawn_start, &pawn_start_horizontal, &knight_start, &knight_start_horizontal);

scanf是一個特別難以正確使用的舊 C 函數,因為您必須手動確保參數的類型與格式字符串中的類型標識符匹配。 當您使用它時,您將不可避免地產生導致未定義行為的編程錯誤。 在這種情況下,您實際上似乎正確地使用了它,盡管我個人認為在這些年之后解析中途復雜的 C 格式字符串仍然有很大的麻煩,所以不要相信我的話。 我不明白你為什么使用抑制賦值的*部分。

您可以通過使用 C++ 流使這變得更加清晰和安全:

std::cin >> pawn_start;
std::cin >> pawn_start_horizontal;
std::cin >> knight_start;
std::cin >> knight_start_horizontal;

或者,什么會更好:使用std::getline將整行輸入讀入std::string並解析該行,這樣您就可以使用錯誤消息響應錯誤的用戶輸入,例如“pawn start horizo​​ntal must be一個號碼”。 Stackoverflow 上有數百個問題,可能還有數千個答案。

在此期間,請考慮使用std::cout而不是printf

我會說去用你的數組修復未定義的行為並使用安全的 I/O。 如果它仍然不起作用,請提出一個新問題,因為問題可能出在其他地方,但只要存在未定義的行為,就沒有進一步推理程序邏輯的意義。

暫無
暫無

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

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