通过无用的printf调用修复了条件返回值错误

时间:2019-04-10 18:34:06

标签: c debugging

我正在尝试为我的简单游戏(学校项目)编写一个用于碰撞检测的简单函数,直到我添加了无意义的printf行(最初是出于预期目的)之前,它无法从中获得合适的返回值。以协助进行调试),并且一切均以某种方式进行。我不知道那是什么虫子?以及如何以更“正确”的方式修复它。谢谢。

这是我的功能(变量“ rect”(矩形)是标准的SDL结构,具有4个整数成员,分别表示其高度,宽度以及拐角的x和y):

bool collision(SDL_Rect *rect1, SDL_Rect *rect2) {
    //chekcs to see if rect2 is totally outside of boundaries of rect1
    static bool collided;
    if (rect1->y > rect2->y + rect2->h) {
        printf("");
        collided = false;
        return collided;
    }
    if (rect1->y + rect1->h < rect2->y) {
        printf("");
        collided = false;
        return collided;
    }
    if (rect1->x > rect2->x + rect2->w) {
        printf("");
        collided = false;
        return collided;
    }   
    if (rect1->x + rect1->w < rect2->x) {
        printf("");
        collided = false;
        return collided;
    }
    //returns 1 if none of above is true

    collided = 1;
    return collided;
}

编辑: 我之所以使用静态布尔值,是因为我试图让Visual Studio在监视窗口中显示布尔变量的值,即使该变量(变量)不在作用域之内,它也不起作用,并且我忘记了删除静态变量。问题是我是否使用静态。

编辑2: 这是调用上面函数的函数(我知道digonalMovement需要一个小小的固定来使对角移动时两个方向的速度变慢(目前只有一个变慢),但这与问题在手):

void player_movement_calc(int player_nr, SDL_Rect char_rects[], Char character[]) {
    // determine velocity
    character[player_nr].x_vel = character[player_nr].y_vel = 0;
    bool collided = collision(&char_rects[0], &char_rects[2]);

    bool digonalMovement = 0;
    if (character[player_nr].up && !character[player_nr].down) {    
        if (digonalMovement)
            character[player_nr].y_vel = -SPEED * 0.86; //multiplying by sin(45)
        else {
            character[player_nr].y_vel = -SPEED;
        }
        digonalMovement = 1;
        if (collided)
            character[player_nr].y_vel -= 2 * character[player_nr].y_vel;
    }
    if (character[player_nr].down && !character[player_nr].up) {
        if (digonalMovement)
            character[player_nr].y_vel = SPEED * 0.86;
        else {
            character[player_nr].y_vel = SPEED;
        }
        digonalMovement = 1;
        if (collided)
            character[player_nr].y_vel -= 2 * character[player_nr].y_vel;
    }
    if (character[player_nr].left && !character[player_nr].right) {
        if (digonalMovement)
            character[player_nr].x_vel = -SPEED * 0.86;
        else {
            character[player_nr].x_vel = -SPEED;
        }
        digonalMovement = 1;
        if (collided)
            character[player_nr].y_vel -= 2 * character[player_nr].y_vel;
    }
    if (character[player_nr].right && !character[player_nr].left) {
        if (digonalMovement)
            character[player_nr].x_vel = SPEED * 0.86;
        else {
            character[player_nr].x_vel = SPEED;
        }
        digonalMovement = 1;
        if (collided)
            character[player_nr].y_vel -= 2 * character[player_nr].y_vel;
    }
    //clears diagonalMovement to make it false for next fram
    digonalMovement = 0;

    // update positions
    character[player_nr].x_pos += character[player_nr].x_vel / 60;
    character[player_nr].y_pos += character[player_nr].y_vel / 60;

    // collision detection with bounds
    if (character[player_nr].x_pos <= 0)
        character[player_nr].x_pos = 0;
    if (character[player_nr].y_pos <= 0)
        character[player_nr].y_pos = 0;
    if (character[player_nr].x_pos >= WINDOW_WIDTH - char_rects[player_nr].w)
        character[player_nr].x_pos = WINDOW_WIDTH - char_rects[player_nr].w;
    if (character[player_nr].y_pos >= WINDOW_HEIGHT - char_rects[player_nr].h)
        character[player_nr].y_pos = WINDOW_HEIGHT - char_rects[player_nr].h;

    // set the positions in the struct 
    char_rects[player_nr].y = (int)character[player_nr].y_pos;
    char_rects[player_nr].x = (int)character[player_nr].x_pos;
}

1 个答案:

答案 0 :(得分:1)

player_movement_calc()函数中,您拥有collision(&char_rects[0], &char_rects[2])。看来您应该将播放器的矩形与

    bool collided = collision(&char_rects[0], &char_rects[1]);

您可能正在读取char_rects数组末尾以外的内容,从而导致未定义的行为。由printf引起的任何副作用,例如为自己的目的分配内存或stdout缓冲区,都可能会改变程序的行为,例如,通过使对超出数组末尾的访问的内存具有可读性,从而消除了崩溃并隐藏了错误。

另一个可能的解释是,如果未使用结果collision并且函数collision没有副作用,则编译器可能会省略对static的调用。如果没有printfstatic,该函数将没有副作用(除了由于读取超出数组末尾(无论如何都是未定义的行为)而导致的崩溃)之外。更改volatile的值可能被编译器认为是无用的,因为此变量未在任何地方使用且未定义printfcollision有副作用,因此调用它会使printf不纯,因此无法忽略该调用。

总是很难尝试去理解未定义的行为。调试时,首先应禁用所有优化。如果不使用BufferedImage并禁用优化,则该错误可能是可见的,而对于未经优化的代码,跟踪代码和查看局部变量应该会容易得多。

一旦在调试版本中出现可重现的崩溃错误,只需使用调试器向您显示错误发生的位置。崩溃错误应易于调查。