0

Я уверен, что вы (профи) можете идентифицировать ошибку в моем коде, я также буду признателен за любые другие комментарии к моему коду.Ошибка динамического распределения памяти

BTW, код падает после запуска.

#include <stdlib.h> 
#include <stdio.h> 
#include <stdbool.h> 

typedef struct 
{ 
    int x; 
    int y; 
} Location; 

typedef struct 
{ 
    bool walkable; 
    unsigned char walked; // number of times walked upon 
} Cell; 

typedef struct 
{ 
    char name[40]; // Name of maze 
    Cell **grid; // 2D array of cells 
    int rows;  // Number of rows 
    int cols;  // Number of columns 
    Location entrance; 
} Maze; 


Maze *maz_new() 
{ 
    int i = 0; 

    Maze *mazPtr = (Maze *)malloc(sizeof (Maze)); 

    if(!mazPtr) 
    { 
     puts("The memory couldn't be initilised, Press ENTER to exit"); 
     getchar(); 
     exit(-1); 
    } 
    else 
    { 
     // allocating memory for the grid 
    mazPtr->grid = (Cell **) malloc((sizeof (Cell)) * (mazPtr->rows)); 

    for(i = 0; i < mazPtr->rows; i++) 
     mazPtr->grid[i] = (Cell *) malloc((sizeof (Cell)) * (mazPtr->cols)); 
    } 

    return mazPtr; 
} 


void maz_delete(Maze *maz) 
{ 
    int i = 0; 

    if (maz != NULL) 
     { 
      for(i = 0; i < maz->rows; i++) 
       free(maz->grid[i]); 

      free(maz->grid); 
     } 
} 


int main() 
{ 
    Maze *ptr = maz_new(); 
    maz_delete(ptr); 

    getchar(); 
    return 0; 
} 

Заранее спасибо.

+0

Почему бы вам не выделить сетку в ходу? например maxPtr-> grid = malloc (sizeof (Cell) * mazPtr-> rows * mazPtr-> cols); Я нахожу доступ к ячейкам, как это концептуально проще. –

ответ

0

Насколько велик лабиринт? Вы никогда не инициализируете rows и cols.

Ваша большая проблема, однако, в том, что вы используете sizeof (Cell) при инициализации grid, но это должно быть sizeof (Cell *).

На моей архитектуре Cell всего два байта, тогда как Cell * - это восемь байтов, что означает, что вы не выделили достаточно места. Когда вы заполняете этот массив, вы пишете его до конца и в какой-то другой фрагмент выделенной памяти, после чего все ставки отключены. Распределитель памяти в какой-то момент искажает содержимое массива, и вы остаетесь пытающимся освободить мусор.

mazPtr->grid = (Cell **) malloc((sizeof (Cell)) * (mazPtr->rows)); 

Вы выделение 10 ячеек, это возвращает указатель на первую ячейку, которая будет типа Cell *:

+0

О, стреляй, наверное, я забыл эту часть:/ В любом случае, я помещаю (10) вместо строк и столбцов, но он все равно не работает. Странно, почему компилятор не узнал, что строки, cols не были инициализированы. Также тот же код даже не разбился на другом компиляторе!?. – m4design

+1

Невозможно, чтобы компилятор обнаружил неинициализированные переменные в общем случае, так как он эквивалентен проблеме остановки. Он не сбой на другом компиляторе, потому что значения неопределенны. Они могут быть 0, -1, случайное число или что угодно. Различные компиляторы, разные версии компилятора и даже разные прогоны одной и той же программы могут давать разные результаты. –

+0

Ага, я получил это, Большое спасибо. Вы идентифицировали другую ошибку, которая вызывает крушение. – m4design

1

В дополнении к проблеме Марсела указал, я это заметил. A Cell struct является bool и unsigned char, который, в зависимости от компилятора и целевой архитектуры, может не выделяться достаточно большим, чтобы удерживать Cell * (который может быть 64-разрядным указателем). Когда вы позже инициализируете свой массив сетки, вы, вероятно, закончите писать концы массива.

Итак, попробуйте выделить 10 sizeof (Cell *) в вашей сетке. И исправить там проблему инициализации.

0

в maz_delete вам нужен еще один вызов, чтобы освободить для МАЗа структуры самой

недействительным maz_delete (Maze * маз) { INT I = 0;

if (maz != NULL) 
{ 
    for(i = 0; i < maz->rows; i++) 
     free(maz->grid[i]); 

    free(maz->grid); 

    free(maz); 
} 

}