尝试在C中读取迷宫文本文件时出现malloc错误 [英] malloc error when trying to read a maze text file in C

查看:84
本文介绍了尝试在C中读取迷宫文本文件时出现malloc错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试从包含以下内容的文本文件中读取代码: (文本文件称为maze1.txt)

I'm trying to get my code to read from a text file that's contents involve: (text file is called maze1.txt)

5 5
%%%%%
S % %
% % %
%   E
%%%%%

但是,每当我尝试运行程序时,都会收到分段错误,我认为这与我使用malloc的方式有关.我知道我已经使用第一个数字来设置数组的边界,但是我不确定如何做到这一点.

However whenever I attempt to run the program I receive a segmentation fault which I think has something to do with how I'm using malloc. I know that I have use the first numbers in order to set boundaries for my array, but I'm unsure on how to do that.

提供我的代码:

provided is my code:

#include <stdio.h>
#include <stdlib.h>
#include "maze.h"
maze_t * createMaze(char * fileName)
{
    typedef struct Maze{
    int cols, rows;
    char **charRow;
    }MAZE;
    struct Maze maze;
    FILE *pf;
    int i,j,k;
    pf = fopen(fileName,"r");
    k = fscanf(pf, "%i %*c %i", &maze.cols, &maze.rows);
    char cMaze[maze.cols][maze.rows];
    int new;
    int *newMaze = (int *)malloc( maze.rows * maze.cols * sizeof(int));
    for(i = 0; maze.rows; i++){
        for(j = 0; j < maze.cols; j++){
            cMaze[i][j] = fgetc(pf);
            putchar( cMaze[i][j] ); 

        }       
    }
    printf("%d", cMaze[maze.cols][maze.rows]);
    printf("\n");
    maze.charRow = newMaze;
    fclose(pf);


    return newMaze;
}

这是我的主要内容:

#include <stdio.h>
#include "maze.h"


int main(int argc, char **argv)
{
    if (argc < 2)
    {
        printf("You need a valid input maze file.\n");
        return -1;
    }

    printf("Creating maze with file %s\n", argv[1]);
    maze_t * maze = createMaze(argv[1]);

    printf("\nUnsolved maze:\n");
    printMaze(maze);

    if(solveMazeManhattanDFS(maze, maze->startColumn, maze->startRow))
    {
        printf("\nSolved maze:\n");
        printMaze(maze);
        if(checkMaze(maze))
        {
            printf("Solution to maze is valid\n");
        }
        else
        {
            printf("Incorrect solution to maze\n");
        }
    }
    else
    {
        printf("\nMaze is unsolvable\n");
    }

    printf("\nDestroying maze\n");

    destroyMaze(maze);

    return 0;
}

结构maze_t的定义是

definition of the struct maze_t is

typedef struct {
    int width;
    int height;
    int startColumn;
    int startRow;
    int endColumn;
    int endRow;
    char ** cells;
} maze_t;

推荐答案

您无法知道createMaze是成功还是失败,因为您无法验证文件是否实际上已打开以供读取.保存fscanf的返回值时,您无法以任何方式验证实际发生过两次转换.

You have no way to know whether createMaze succeeds or fails because you fail to validate that your file is actually open for reading. While you save the return of fscanf, you fail to validate in any way that 2 conversions actually took place.

对于第一行,使用fscanf很好,但是请理解'\n'留在stdin中,您必须在下一次读取之前考虑到这一点. (您的下一个读取值为fgetc -很高兴将'\n'作为文件中的下一个值,并将其分配给cMaze[0][0].

Using fscanf is fine for the first row, but understand that the '\n' is left in stdin and you must account for that before your next read. (your next read being fgetc -- it will happily take '\n' as the next value in the file and assign it to cMaze[0][0].

2D数组等同于char **.如果计划存储组成迷宫的行并通过char **charRow;引用它们,则需要为char分配maze.rows个指针,然后需要为每行分配存储并为以下行分配起始地址每个maze.charRow[x]的那个存储块. (对于行输入,fgets是阅读每行的更好选择)

A 2D array is not equivalent to char **. If you plan on storing the lines that make up the maze and referencing them through char **charRow;, then you need to allocate maze.rows number of pointers to char, and you then need to allocate storage for each line and assign the beginning address for that block of storage to each maze.charRow[x]. (for line oriented input, fgets is a better choice for reading each line)

您分配了newMaze,但未分配任何值.

You allocate for newMaze, but do not assign any values.

让我提供一个示例,以正确验证您需要执行的每个步骤,将每行存储在maze.line[x](已重命名为charRow)中,使用存储的值输出迷宫,而不是为您修复现有的代码.然后在退出之前释放分配的所有内存(每行+指针).每个单独的验证都在下面的内嵌评论中进行了描述,例如

Rather than fixing your existing code for you, let me provide an example that properly validates each step you need to take, stores each line in maze.line[x] (your renamed charRow), outputs the maze using the stored values and then frees all memory allocated (each line + the pointers) before exiting. Each individual validation is described in the comments, in-line, below, e.g.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#ifndef BUF_SIZ
#define BUF_SIZ 8192
#endif

typedef struct {
    int cols, rows;
    char **line;
} maze_t;

void *xcalloc (size_t nmemb, size_t sz);

int main (int argc, char **argv) {

    char buf[BUF_SIZ] = "";
    int n = 0;
    maze_t maze;
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;

    if (!fp) {  /* validate file open for reading */
        fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
        return 1;
    }

    /* read maze.rows & maze.cols */
    if (fscanf (fp, "%d %d", &maze.rows, &maze.cols) != 2) {
        fprintf (stderr, "error: failed to read rows & cols.\n");
        return 1;
    }
    fgets (buf, BUF_SIZ, fp);   /* read discard any additional chars */

    /* allocate/validate maze.rows pointers */
    maze.line = xcalloc (maze.rows, sizeof *maze.line);

    /* read each remaining line up to maze.rows lines */
    while (n < maze.rows && fgets (buf, BUF_SIZ, fp)) {
        size_t len = strlen (buf);      /* get buf length */
        if (len && buf[len-1] == '\n')  /* validate last char is '\n' */
            buf[--len] = 0;             /* overwrite with nul-character */
        else {      /* line too long, handle error */
            fprintf (stderr, "error: line exceeds BUF_SIZ.\n");
            return 1;
        }
        if (len != (size_t)maze.cols) { /* validate maze.cols chars read */
            fprintf (stderr, "error: line exceeds maze.cols.\n");
            return 1;
        }

        /* allocate/validate maze.cols +1 chars */
        maze.line[n] = xcalloc (len + 1, sizeof *maze.line[n]);
        strcpy (maze.line[n++], buf);   /* copy buf to maze.line[n] */
    }

    if (fp != stdin) fclose (fp);   /* close file if not stdin */

    if (n != maze.rows) {   /* validate maze.rows lines read */
        fprintf (stderr, "error: less than maze.rows lines read.\n");
        return 1;
    }

    for (int i = 0; i < n; i++) {
        printf ("%s\n", maze.line[i]);  /* output each line */
        free (maze.line[i]);            /* free line */
    }
    free (maze.line);                   /* free pointers */

    return 0;
}

/** xcalloc allocates memory using calloc and validates the return.
 *  xcalloc allocates memory and reports an error if the value is
 *  null, returning a memory address only if the value is nonzero
 *  freeing the caller of validating within the body of code.
 */
void *xcalloc (size_t nmemb, size_t sz)
{
    register void *memptr = calloc (nmemb, sz);
    if (memptr == 0) {
        perror ("xcalloc() error: virtual memory exhausted.");
        exit (EXIT_FAILURE);
    }

    return memptr;
}

希望这将为您需要在代码中更正的每个步骤提供一个可行的示例. (注意:上面的xcalloc函数只是为了方便起见,避免在代码正文中重复进行验证)

Hopefully this will provide a working example of each of the steps you need to correct in your code. (note: the xcalloc function is just for convenience above to keep from duplicating the validations in the body of the code)

使用/输出示例

$ ./bin/maze <dat/maze.txt
%%%%%
S % %
% % %
%   E
%%%%%

内存使用/错误检查

在您编写的任何动态分配内存的代码中,对于任何分配的内存块,您都有2个职责:(1)始终保留指向起始地址的指针因此,(2)当不再需要它时,可以释放.

In any code you write that dynamically allocates memory, you have 2 responsibilities regarding any block of memory allocated: (1) always preserve a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed.

对于Linux valgrind是正常选择.每个平台都有类似的内存检查器.它们都很容易使用,只需通过它运行程序即可.

For Linux valgrind is the normal choice. There are similar memory checkers for every platform. They are all simple to use, just run your program through it.

$ valgrind ./bin/maze <dat/maze.txt
==18822== Memcheck, a memory error detector
==18822== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==18822== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==18822== Command: ./bin/maze
==18822==
%%%%%
S % %
% % %
%   E
%%%%%
==18822==
==18822== HEAP SUMMARY:
==18822==     in use at exit: 0 bytes in 0 blocks
==18822==   total heap usage: 6 allocs, 6 frees, 70 bytes allocated
==18822==
==18822== All heap blocks were freed -- no leaks are possible
==18822==
==18822== For counts of detected and suppressed errors, rerun with: -v
==18822== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

始终确认已释放已分配的所有内存,并且没有内存错误.

Always confirm that you have freed all memory you have allocated and that there are no memory errors.

仔细研究一下,努力将验证合并到您的代码中,如果您还有其他问题,请与我联系.

Look things over, work to incorporate the validations in your code and let me know if you have any further questions.

这篇关于尝试在C中读取迷宫文本文件时出现malloc错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆