简体   繁体   中英

rand() generating different values when used in valgrind

I'm trying to randomly generate rooms in a two-dimensional array of size 100x100. If the room being generated collides with an already existing room, it generates new points for the room. The generation code makes sense conceptually, but when I try to run, the program loops endlessly, and checking the log reveals why.

Room created successfully with dimensions x=0, y=0, width=976761120, height=809120052

For some reason, at lines 65-68, inside create_room(), the width and height for the room are being randomly assigned huge numbers, when they should be between 1 and 11. Just for fun, I ran the program through Valgrind using the options --track-origins=yes -v, and I what I found surprised me. Suddenly, the program would run!

Room created successfully with dimensions x=0, y=0, width=0, height=0

While still not exactly what I wanted, this at least prevents an infinite loop of collisions being detected with an impossibly huge room.

So, my question is, why is the code generating such large numbers when executed normally, but generate smaller numbers when in Valgrind?

Here's the code for the program.

#include <time.h>
#include <stdlib.h>
#include "global.h"
#include "draw.h"
#include "log.h"
#include "generate.h"
#define NUM_ROOMS 10
#define ROOM_SIZE 10
#define MAP_HEIGHT 100
#define MAP_WIDTH 100

static struct ROOM* create_room (unsigned int);

struct ROOM {
    int x, y, width, height; 
    int feature;
};

struct ROOM* rooms[NUM_ROOMS] = {NULL};

static FILE* gen_log;

static WINDOW* gen_window;

int** generate_dungeon(unsigned int seed){
    char* log_entry = malloc (80);
    int i = 0, j, k;
    gen_window = create_window (0, 0, LINES, COLS);

    gen_log = log_open (GEN_LOG);
    if (seed == 0){
        time_t t;
        seed = time (&t);
    }
    srand (seed); 
    for (int i = 0; i < NUM_ROOMS; i++){
        rooms[i] = create_room (seed);
        sprintf (log_entry,"Room created successfully with dimensions x=%d, y=%d, width=%d, height=%d\n", rooms[i]->x, rooms[i]->y, rooms[i]->width, rooms[i]->height);
        LOG_DEBUG (gen_log,log_entry);
    }
    LOG_DEBUG(gen_log, "Beginning to draw rooms\n");
    for (i=0;i < NUM_ROOMS;i++){
        sprintf (log_entry, "Drawing room %d\n", i);
        LOG_DEBUG (gen_log, log_entry);
        for (j = rooms[i]->y; j < rooms[i]->y + rooms[i]->height; j++){
            for (k = rooms[i]->x; k < rooms[i]->x + rooms[i]->width; k++){
                sprintf (log_entry, "Clearing %d,%d]\n", j,k);
                LOG_DEBUG (gen_log, log_entry);
                map_array[j][k] = 1;
            }
        }
    }
    destroy_window (gen_window);
}

static struct ROOM* create_room (unsigned int seed){
    int i = 0, flag; 
    srand (seed);
    if (rooms[0] == NULL)
        flag = 0;
    else
        flag = 1;
    char* log_entry = malloc (80);
    struct ROOM* new_room = malloc (sizeof(struct ROOM));
    while (flag){
        draw_notify (gen_window, "Creating room\n");
        new_room->x = (rand() % MAP_WIDTH);
        new_room->y = (rand() % MAP_HEIGHT);
        new_room->width =  (rand() % ROOM_SIZE + 1);
        new_room->height = (rand() % ROOM_SIZE + 1);

        sprintf (log_entry, "New room created with points x=%d, y=%d,width=%d, height=%d\n", new_room->x, new_room->y, new_room->width, new_room->height);
        LOG_DEBUG (gen_log, log_entry);
        draw_notify (gen_window, "Log entry made\n");

        if (new_room->x + new_room->width >= MAP_WIDTH || new_room->y + new_room->height >= MAP_HEIGHT){
            LOG_DEBUG (gen_log, "Room out of bounds\n");
            continue;
        }
        i=0;
        draw_notify(gen_window, "Entering loop\n");
        while (rooms[i] != NULL && i < NUM_ROOMS){
            sprintf (log_entry, "Testing room %d\n", i);
            draw_notify (gen_window, log_entry);
            LOG_DEBUG(gen_log, log_entry);
            if (new_room->x < rooms[i]->x + rooms[i]->width && 
                new_room->x + new_room->width > rooms[i]->x && 
                new_room->y < rooms[i]->y + rooms[i]->height &&
                new_room->y + new_room->height > rooms[i]->y){
                    sprintf (log_entry, "Collision detected with room %d\n", i);
                    draw_notify (gen_window, log_entry);
                    LOG_DEBUG (gen_log, log_entry);
                    flag = 1;
                    break;
            }
            else{
                sprintf (log_entry, "Room %d passed.\n", i);
                flag = 0;
                i++;
            }
        }
        draw_notify(gen_window, "Exited loop\n");
    }
    return new_room;
}

You have some logic errors and end up with uninitialized values.

You initialize rooms to be an array of NULL pointers.

In create_room , you have:

if (rooms[0] == NULL)
    flag = 0;
else
    flag = 1;

First time around, flag will be set to 0 . And then, you use:

struct ROOM* new_room = malloc (sizeof(struct ROOM));
while (flag){

since flag is set to 0 , nothing under the while gets executed and you end up with uninitialized members in new_room .

You need to re-think your logic and make sure that you initialize members of new_room always.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM