Освобождение динамически размещаемой 2D-структуры - PullRequest
0 голосов
/ 20 июля 2011

Я динамически выделил структуру, концептуально очень похожую на матрицу, для хранения набора строк. Я столкнулся с проблемой при попытке освободить память. Мой код выглядит так:

# include <stdio.h> 
# include <string.h>
# include <malloc.h>
# define SIZE 2

typedef struct fork{
char** dataPointersArray;
char*  dataArray;
}fork;

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

fork forkDS;
int i;
char* dataArrayPtr;
unsigned char data[255] = "some data"; /* this is actually a function's output */
int PtrIndex;

/* allocate memory for the arrays */
    forkDS.dataPointersArray = (char**) calloc(SIZE ,sizeof(char*));

    if(forkDS.dataPointersArray == NULL){
        printf("couldn't allocate memory \n");

    }

    forkDS.dataArray = (char*) calloc(SIZE, 255);

    if( forkDS.dataArray == NULL){
        free(forkDS.dataPointersArray);
        printf("couldn't allocate memory \n");

    }
    dataArrayPtr = forkDS.dataArray;
    for(i = 0; i < SIZE; i++){
    /* update the dataPointers Array */
        forkDS.dataPointersArray[i] = dataArrayPtr;


        /* copy data into data array */
        memcpy(dataArrayPtr,data,20);

        dataArrayPtr[255] = '\0';

        /* update the pointer of the data array */
        dataArrayPtr = dataArrayPtr + 256;
    }


    for (PtrIndex = 0; PtrIndex < 2; PtrIndex++) {
        if (*(forkDS.dataPointersArray + PtrIndex) != NULL) {
            *(forkDS.dataPointersArray + PtrIndex) = NULL;
        }
    }

    /* DEBUG comment -  this 2 lines works */
    free(forkDS.dataArray); 
    forkDS.dataArray = NULL;

    /* DEBUG comment - the next line fails */
    free(forkDS.dataPointersArray);
    forkDS.dataPointersArray = NULL;


return 0;
}

Таким образом, структура на самом деле содержит 2 массива, один из которых содержит указатели на строки, а другой содержит строки, выровненные одна за другой, разделенные завершающим \ 0.

Код работает нормально, и цикл for в конце также работает. Первый звонок на бесплатный тоже работает. Проблема в том, что последний звонок на бесплатный проваливается. Несмотря на попытки поиска всех возможных данных по проблеме, все примеры, которые я нашел, рассматривали случай, когда второй массив, содержащий строки, размещается шаг за шагом в цикле for, а затем освобождается в цикле for. ,

Я хотел избежать использования динамического выделения в цикле, и поэтому мой код выглядит иначе.

Кто-нибудь знает, в чем проблема?

=============================================== =======================================

Большое спасибо всем, кто ответил мне. В конце концов, ошибка была решена. Проблема заключалась в том, что dataPointersArray был заполнен не только элементами SIZE в каком-то другом фрагменте кода, который сначала казался невинным и фактически приводил к сбою бесплатного вызова.

Еще раз спасибо за комментарии! Шахар

Ответы [ 2 ]

6 голосов
/ 20 июля 2011

Вы выделяете РАЗМЕР * 255 байтов, но используете РАЗМЕР * 256 байтов:

forkDS.dataArray = (char*) calloc(SIZE, 255); 
dataArrayPtr = forkDS.dataArray;   

//SIZE TIMES loop:
    dataArrayPtr = dataArrayPtr + 256; 

Таким образом, когда вы обнуляете указатели, вы, вероятно, перезаписываете управляющие данные, размещенные за концом массива, malloc, который ищет free.

0 голосов
/ 21 июля 2011

Вы выделили пространство для массива, состоящего из строк размера с 255 символами в каждой.Поэтому самый высокий индекс в каждой строке равен 254 = 255 - 1. Когда вы пишете символ \ 0, вы пишете его в начале следующей строки.После последней итерации вы были бы выключены байтами SIZE.

Еще одна деталь: в случае сбоя выделения памяти программа выдаст только сообщения об ошибках, но не перестанет вызывать SEGFAULT позже..

...