当前位置 : 首页 » 互动问答 » 正文

尝试读取C中的迷宫文本文件时发生malloc错误

分类 : 互动问答 | 发布时间 : 2018-04-27 15:43:50 | 评论 : 3 | 浏览 : 55 | 喜欢 : 0

我试图让我的代码从文本文件中读取,其内容包括: (文本文件名为maze1.txt)

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

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

提供的是我的代码:

 #include <stdio.h>
#include <stdlib.h>
#include“maze.h”
maze_t * createMaze(char * fileName)
{
    typedef struct Maze {
    int cols,rows;
    char ** charRow;
    }迷宫;
    结构迷宫迷宫;
    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);


    返回newMaze;
}

,这里是我的main:

 #include <stdio.h>
#include“maze.h”


int main(int argc,char ** argv)
{
    如果(argc <2)
    {
        printf(“你需要一个有效的输入迷宫文件。\ n”);
        返回-1;
    }

    printf(“用文件%s创建迷宫\ n”,argv [1]);
    maze_t * maze = createMaze(argv [1]);

    printf(“\ n未解决的迷宫:\ n”);
    printMaze(迷宫);

    if(solveMazeManhattanDFS(maze,maze-> startColumn,maze-> startRow))
    {
        printf(“\ n解决迷宫:\ n”);
        printMaze(迷宫);
        如果(checkMaze(迷宫))
        {
            printf(“迷宫解决方案有效\ n”);
        }
        其他
        {
            printf(“错误的迷宫解决方案\ n”);
        }
    }
    其他
    {
        printf(“\ nMaze is unsolvable \ n”);
    }

    printf(“\ nDestroying maze \ n”);

    destroyMaze(迷宫);

    返回0;
}

struct maze_t的定义是

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

回答(3)

  • 1楼
  • 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.

    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].

    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)

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

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

    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)

    Example Use/Output

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

    Memory Use/Error Check

    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.

    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.

  • 2楼
  • 我认为你的问题是这样的:

     k = fscanf(pf,“%i%* c%i”,&maze.cols,&maze.rows);
    

    使用输入

    5 5
    

    ,您不会得到maze.rows初始化。 %*c将“吃”(压缩)第二个5.

    试试这个来调试你的代码:

     k = 0;
    maze.cols = 0;
    maze.rows = 0;
    k = fscanf(pf,“%i%* c%i”,&maze.cols,&maze.rows);
    printf(“%d%d%d \ n”,k,maze.cols,maze.rows);
    

    并检查打印的值。我得到的值是:

    1 5 0
    

    so maze.rows没有被fscanf

    赋值之后,试试这个:

     k = fscanf(pf,“%i%i”,&maze.cols,&maze.rows);
  • 3楼
  • 您需要正确读取如下所示的行和列号。

     k = fscanf(pf,“%d%d”,&maze.cols,&maze.rows);
    

    另外,你的for语句有一些错误。它必须是这样的。

     for(i = 0; i <= maze.rows; i ++){
        for(j = 0; j <= maze.cols; j ++){
            cMaze [i] [j] = fgetc(pf);
            的putchar(cMaze [i] [j]);
        }
    }
    编辑:试试我为你的createMaze编写的代码。如果您不明白,可随时提出更多问题。<math_t * createMaze(char * fileName)
    {
        typedef struct Maze {
            int cols,rows;
            char ** charRow;
        }迷宫;
        结构迷宫迷宫;
        FILE * pf;
        int i,j,k;
        pf = fopen(fileName,“r”);
        k = fscanf(pf,“%d%d”,&maze.cols,&maze.rows);
        int * newMaze =(int *)malloc(maze.rows * maze.cols * sizeof(int));
        for(i = 0; i <= maze.rows; i ++){
            for(j = 0; j <= maze.cols; j ++){
                newMaze [i + j] = fgetc(pf);
                的putchar(newMaze [I + J]);
            }
        }
        的printf( “\ n”);
        FCLOSE(PF);
    
        返回newMaze;
    }

    Edit: Try the code I wrote for your createMaze. If you don't understand feel free to ask more questions.

    struct 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, "%d %d", &maze.cols, &maze.rows);
        int *newMaze = (int *)malloc(maze.rows * maze.cols * sizeof(int));
        for (i = 0; i <= maze.rows; i++) {
            for (j = 0; j <= maze.cols; j++) {
                newMaze[i+j] = fgetc(pf);
                putchar(newMaze[i+j]);
            }
        }
        printf("\n");
        fclose(pf);
    
        return newMaze;
    }
    

相关阅读: