Сбой программы при попытке освободить 2D-динамический выделенный массив

Вообще сложно понять, что и почему происходит. В начале программы я объявляю два 2D динамических массива (все используемые в программе массивы имеют одинаковые размеры):

int **initial_array;
int **new_array; 

Затем выделяю необходимую память:

//dynamic allocate arrays (1st Dimension)
initial_array = calloc(N,sizeof(int));
new_array = calloc(N,sizeof(int));

//check if the memory has been allocated correctly
if (initial_array==NULL || new_array==NULL) 
{
    printf("Error allocating memory!\n"); //print an error message
    return 1; //return with failure
}

for (i=0;i<N;i++)
{
    //dynamic allocate arrays (2nd Dimension)
    initial_array[i] = calloc(P, sizeof(int));
    new_array[i] = calloc(P, sizeof(int));
}

Затем я вызываю функцию, которая принимает значения исходного массива, генерирует другой динамический 2D-массив, который я печатаю (внутри функции) и освобождаю (путем вызова другой функции) без проблем, и сохраняю этот массив в new_array:

new_array = create_new_array(some_data, initial_array);

Затем я сохраняю значения в initial_array:

for (i=0;i<N;i++)
{
    for (p=0;p<P;p++)
    {
        initial_array[i][p] = new_array[i][p];
    }
}

free_array_in_function(new_array);

Все идет нормально. Проблема возникает, когда я освобождаю массивы. Initial_array отлично работает:

//free memory
for (i=0;i<N;i++)
{
    free(initial_array[i]);
}

free(initial_array);

Затем я пытаюсь использовать new_array, но программа вылетает:

//free memory
for (i=0;i<N;i++)
{
    free(new_array[i]);
}

free(new_array);


ERROR: Unhandled exception at 0x102d12b4 (msvcr90d.dll) in Genetic_v1.exe: 
0xC0000005: Access violation reading location 0xfeeefee8.

Любые идеи, почему это происходит?

//Function
int **create_new_array(double *some_data, int **individuals_table)
{
      int **children;

     //dynamic allocate array of children (1st Dimension)
     children = calloc(N,sizeof(int));

     //check if the memory has been allocated correctly
     if (children==NULL) 
     {
        printf("Error allocating memory!\n"); //print an error message
        return 1; //return with failure
     }

     for (cv01=0;cv01<N;cv01++)
     {
        //dynamic allocate array of Individuals (2nd Dimension)
        children[cv01] = calloc(P, sizeof(int));

        //check if the memory has been allocated correctly
        if (children[cv01]==NULL) 
        {
           printf("Error allocating memory!\n"); //print an error message
           return 1; //return with failure
        }
    }

    //Do some calculations

    return children;
}

person kat    schedule 17.12.2014    source источник
comment
В create_new_array вы делаете любое распределение памяти. Можешь это опубликовать??   -  person Karthikeyan.R.S    schedule 17.12.2014
comment
@ Karthikeyan.R.S Я просто публикую это в вопросе.   -  person kat    schedule 17.12.2014
comment
В функции free_array_in_function вы освобождаете память??   -  person Karthikeyan.R.S    schedule 17.12.2014
comment
@ Karthikeyan.R.S да, знаю.   -  person kat    schedule 17.12.2014


Ответы (3)


Поскольку ваше первое распределение неверно

initial_array = calloc(N,sizeof(int));
new_array = calloc(N,sizeof(int));

должно быть

initial_array = calloc(N,sizeof(int *));
new_array = calloc(N,sizeof(int *));

скорее всего вы пытаетесь использовать этот код на 64bit ОС, иначе он мог сработать случайно.

Также вы перезаписываете указатель new_array, который вам не нужен.

new_array = calloc(N,sizeof(int));

или это внутри цикла for

new_array[i] = calloc(P, sizeof(int));

так как у вас есть это

new_array = create_new_array(some_data, initial_array);

И, наконец, комментарий

free_array_in_function(new_array);

потому что вы дважды освобождаете один и тот же указатель. И когда вы пытаетесь получить доступ к массивам в

free(initial_array[i]);

вы разыменовываете указатель, который уже был освобожден.

Это не то, как работают указатели, когда вы calloc в первый раз получаете pointer, то есть целочисленное значение, которое представляет виртуальный адрес в памяти, если вы снова calloc и назначаете предыдущий указатель, то вы перезаписываете адрес и, таким образом, вызываете память утечка.

Затем вы free указатель, который вы выделили функцией create_new_array, но вы не можете free первый calloced указатель, так как вы потеряли ссылку на него.

person Iharob Al Asimi    schedule 17.12.2014
comment
если вы будете явно инициализировать массив, используйте malloc вместо calloc. - person Iharob Al Asimi; 17.12.2014
comment
Это будет синтаксис malloc нет? Я думаю, что каллок такой. В любом случае, я пробовал, но это не решает проблему. - person kat; 17.12.2014
comment
@kat, пожалуйста, опубликуйте свою функцию create_new_array. - person Iharob Al Asimi; 17.12.2014
comment
Я также должен изменить второе распределение, потому что вы все даете мне одно и то же решение, но у меня та же проблема. - person kat; 17.12.2014
comment
@kat и что такое free_array_in_function? - person Iharob Al Asimi; 17.12.2014
comment
функция для освобождения массива в функции: create_new_array - person kat; 17.12.2014
comment
Хорошо, если я правильно понимаю, я не должен освобождать указатель внутри функции, верно? - Для той части, о которой вы говорите, мне не нужно делать второе распределение 'new_array = calloc(N,sizeof(int));' я немного потерялся. Вызывая функцию создания массива, я автоматически резервирую необходимую память? - person kat; 17.12.2014
comment
@kat Точно, ты не такой уж и потерянный. А так как вы перезаписываете указатель, то вы free делаете это дважды. Один раз в free_array_in_function, а затем вы пытаетесь снова в цикле for, отсюда и segmentation fault. - person Iharob Al Asimi; 17.12.2014
comment
Итак, если я правильно понимаю, проблема заключается в этой функции: 'void free_array_in_function(int **children) { int cv01=0; для (cv01=0;cv01‹N;cv01++) {бесплатно(дети[cv01]); } бесплатно (дети); }' Так что я должен опустить это правильно? - person kat; 17.12.2014
comment
Вы должны, а также удалить первый calloc из new_array. - person Iharob Al Asimi; 17.12.2014
comment
БОЛЬШОЕ СПАСИБО... за ваше терпение, ваше время и помощь! - person kat; 17.12.2014

sizeof(int) не то же самое, что sizeof(int *). Даже когда-то это может быть то же самое, в зависимости от платформы, которую вам нужно использовать sizeof(int *) здесь, т.е. сначала выделить память для хранения ваших указателей.

Для тебя

int **initial_array = calloc(N,sizeof(int *));
int **new_array = calloc(N,sizeof(int *));

Позже вам нужно выделить память для ваших указателей индивидуально. Теперь у вас должно быть:

initial_array[i] = calloc(P,sizeof(int));
person Gopi    schedule 17.12.2014

В free_array_in_function(new_array)вы освобождаете память, из-за которой вы получаете ошибку. Причина, по которой вы освобождаете память дважды.

person Karthikeyan.R.S    schedule 17.12.2014