[英]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 horizontal must be一個號碼”。 Stackoverflow 上有數百個問題,可能還有數千個答案。
在此期間,請考慮使用std::cout
而不是printf
。
我會說去用你的數組修復未定義的行為並使用安全的 I/O。 如果它仍然不起作用,請提出一個新問題,因為問題可能出在其他地方,但只要存在未定義的行為,就沒有進一步推理程序邏輯的意義。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.