c - rand() 在 valgrind 中使用时生成不同的值

标签 c random

我正在尝试在大小为 100x100 的二维数组中随机生成房间。如果正在生成的房间与已经存在的房间发生碰撞,它会为该房间生成新的点。生成代码在概念上是有意义的,但是当我尝试运行时,程序无限循环,检查日志揭示了原因。

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

出于某种原因,在 create_room() 内部的第 65-68 行,房间的宽度和高度被随机分配为巨大的数字,而它们应该在 1 到 11 之间。为了好玩,我运行了程序Valgrind 使用选项 --track-origins=yes -v,我的发现让我感到惊讶。突然,程序运行起来了!

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

虽然仍然不是我想要的,但这至少可以防止无限循环的碰撞被检测到一个不可能巨大的房间。

那么,我的问题是,为什么代码在正常执行时会生成如此大的数字,但在 Valgrind 中生成的数字却较小?

这是程序的代码。

#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;
}

最佳答案

你有一些逻辑错误并以未初始化的值结束。

您将 rooms 初始化为 NULL 指针数组。

create_room 中,您有:

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

第一次,flag 将被设置为 0。然后,您使用:

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

由于 flag 设置为 0while 下的任何内容都不会执行,您最终会在 new_room< 中得到未初始化的成员.

您需要重新考虑您的逻辑并确保始终初始化 new_room 的成员。

关于c - rand() 在 valgrind 中使用时生成不同的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32803956/

相关文章:

c - 引用另一个 C 源文件中声明的 volatile 变量时是否需要 extern 关键字?

powershell - 从哈希表中获取随机项,但值的总和必须等于设定的数字

c - 这是最佳的转变方式吗?

c - 如何防止在 USB 传输中丢失数据?

c - 使用指针替换值

c++随机数生成器,允许用户选择范围

java - 限制重复的随机数

c - 使用外部文件中的信息,如何使用 fread 正确填充数组?

c++ - 实现 64 位 Mersenne Twister - 定义

swift - 线程 1 : EXC_BAD_INSTRUCTIONS | SWIFT