堆栈粉碎检测到 C++

Stack smashing detected C++

我正在写一个小程序。我正在 Windows 上工作。我在我的 Ubuntu 上重写了这个程序的精确副本。但是在 Ubuntu 中,我每次执行我的程序时都会遇到堆栈粉碎错误。在两个 OS 中,我都使用代码块 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;
}

我怎样才能避免这个错误?

I have working build on my Windows. I rewrite exact copy of this program on my Ubuntu. But in Ubuntu i get stack smashing error every time i execute my program.

首先,仅说明您的操作系统名称是不够的。在任何这些系统上都有 多个编译器 可用。更不用说理论上 "Windows" 可以是从 Windows 1 到 Windows 10 的所有值,而且 "Ubuntu" 也不是一个非常精确的定义。而且编译器有不同的版本和不同调用选项的无穷组合。

其次,如果 "stack smashing error" 你的意思是分段错误,程序也会崩溃 "on Windows"。我刚刚在我的 Windows 7 64 位机器上用 /EHsc /Za 在 MSVC 2013 上试过它。在我用或多或少的随机输入(我刚输入 12、2 和 2)对其进行测试后,它崩溃了。

How can i prevent this error?

通过避免 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 a number". Whosebug 上有数百个问题,可能还有数千个答案。

当你这样做的时候,考虑使用 std::cout 而不是 printf

我会说去修复数组的未定义行为并使用安全 I/O。如果它仍然不起作用,请提出一个新问题,因为问题很可能出在其他地方,但只要存在未定义的行为,进一步推理程序的逻辑就没有意义。