2015-05-14 4 views
4

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

// integer double pointer to 2d array 
void** idp_to_2d (int rows , int cols) { 
    int i ; 
    void **est = malloc (rows * sizeof (int*)) ; 
    for (i = 0 ; i <= rows ; i ++) 
     est[i] = malloc (cols * sizeof (int)) ; 
    return est ; 
} 

Тогда я получаю этот указатель, используя следующий код из main():

int **est = (int**) idp_to_2d (rows , cols) ; 

Он отлично работает, и я могу индексировать как est[i][j] означающего память была выделена правильно.

Теперь я освободить память в main(), используя код, который следует:

int i ; 
for (i = 0 ; i <= rows ; i ++) 
    free (est[i]) ; 
free (est) ; 

Теперь я получаю двойной бесплатно или коррупционный ошибку.

Мой компилятор GCC 4.9.2, OS является Ubuntu 15,04 (64-разрядная версия), и я использую NetBeans IDE 8.0.2.

+5

проблема с [* неопределенное поведение *] (http://en.wikipedia.org/wiki/Undefined_behavior) является то, что это может показаться * * работать нормально, и у вас есть неопределенное поведение, когда вы идете вне границ выделенной памяти. –

ответ

11

Ваша за петли неправильно - вы Перебор один слишком много строк - изменение:

for (i = 0 ; i <= rows ; i ++) 
       ^^^ 

к:

for (i = 0 ; i < rows ; i ++) 
       ^^^ 

в обоих malloc петли и петли free.


Кроме того, несмотря на то, что это не ошибка, как, например, вы должны действительно изменить:

void** idp_to_2d(... 

к:

int** idp_to_2d(... 

и конечно:

void **est = malloc(... 

к:

int **est = malloc(... 

, поскольку функция возвращает int ** не void **. (Там действительно нет никакого смысла в использовании void ** в любом из кода.)

Вы также можете отказаться от излишних (и потенциально опасного) бросания возвращаемого значения, так:

int **est = (int**) idp_to_2d (rows , cols) ; 

бы просто:

int **est = idp_to_2d (rows , cols) ; 
+1

вы даже не должны указывать указатели void в C –

+0

@ErikW: хорошая точка. –

+0

@ErikW: 'void ** est;' не определяет указатель 'void'. – alk

Смежные вопросы