[英]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.