检测到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格式字符串仍然有很大的麻烦,所以不要相信我的话。我不明白你为什么要用抑制分配的*
部件。
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 a number"。在Stackoverflow上有数百个问题和可能数千个答案。
当你在使用std::cout
时,考虑使用printf
。
我会说去修复未定义的行为与你的数组和使用安全的I/O。如果它仍然不工作,问一个新的问题,因为问题可能在其他地方,但只要存在未定义的行为,进一步推断程序的逻辑是没有意义的。
- 算法问题:查找从堆栈中弹出的所有序列
- 使用模板进行堆栈实现; "name followed by :: must be a class or namespace"
- Visual Studio(或任何其他工具)能否将地址解释为调用堆栈(boost上下文)的开头
- 为什么调用堆栈数组会导致内存泄漏
- gdb错误:Backtrace已停止:上一帧与此帧相同(堆栈已损坏?)
- 在 leetcode 上提交解决方案时出现堆栈缓冲区溢出错误
- 我的 int main() 中出现堆栈溢出错误
- 堆栈和队列是否像C++中的数组一样传递?
- 拥有映射的现代方法,该映射可以指向或引用已在堆栈上分配的不同类型的数据
- 为什么 STL 容器适配器堆栈中的 top 返回常量引用?
- 从堆栈分配的原始指针构造智能指针
- 在函数范围内在堆栈上分配的数组在离开函数时是否总是被释放?
- 堆栈中大小变量输入错误 (C++)
- 堆栈问题(平衡表达式问题集)
- C++ 在堆栈中包含多态属性的类对象存储
- 用于解析 win64 堆栈跟踪的命令行客户端(可以访问符号服务器)
- 在 C++ 中使用链表进行堆栈
- 变量周围的堆栈'...'已损坏
- 在 gtest 中初始化堆栈上的引用变量的隔离错误
- C++线程的可用堆栈大小