Realloc внутри пустой функции - PullRequest
0 голосов
/ 18 января 2019

У меня проблема с утечками памяти при использовании realloc внутри функции, которую я хочу оставить недействительной. Код, который я создаю, предназначен для преобразования типа данных с разреженной матрицей из «CSR» в формат «дельта-единицы», называемый «CSR-DU».

Файл заголовка для функции-нарушителя, содержащий realloc:

void csr_to_csrdu(..., int *ctl_size, uint64_t **ctl, ...);

ctl - это двойной указатель, указывающий на данные массива, который будет изменен и изменен при заполнении массива через realloc. Массив имеет динамический размер, и невозможно определить окончательный размер до выполнения. Отсюда необходимость указателя на размер массива и двойного указателя для хранения адреса памяти массива данных обратно в main ().

В основном ():

ctl = (uint64_t **) malloc( sizeof(uint64_t *) );
ctl_data = (uint64_t *) malloc( *ctl_size * sizeof(uint64_t) );

*ctl= ctl_data; // point to memory data

// call data type conversion
csr_to_csrdu(..., ctl_size, ctl, ...);

// compute sparse matrix-vector multiplication w/ ctl
spmv_csrdu(..., ctl_size, *ctl, ...);

// free ctl data - my problem!
free( ??? );

Внутри функции realloc выглядит примерно так (некоторый псевдо-код):

if( ctl_index >= *ctl_size )
{
    int estimate  = get_estimate();
    tempPtr = realloc(*ctl, (*ctl_size + estimate)*sizeof(uint64_t) );

    if( tempPtr  == NULL ){ 
      print_fatal_error();
      exit();
    }else{ 
      *ctl = tempPtr;
    }
}

Однако я не могу понять, как освободить "ctl_data" после того, как внутри функции произошел перераспределение. Адрес, который у меня изначально был в main (), был уничтожен. Вещи, которые я пытался безрезультатно:

// both cause "double free or corruption" crash
free( ctl_data );   
free( *ctl );

Я не уверен, как действовать здесь. Есть ли способ сделать так, чтобы я мог безопасно освободить "tempPtr", который был создан внутри функции?

1 Ответ

0 голосов
/ 18 января 2019

Краткий ответ:

free(*ctl);
free(ctl);

Когда вы звоните realloc, он может освобождать или не освобождать указатель, который вы изначально выделили (что было ctl_data в main), что означает, что ctl_data может больше не быть действительным для освобождения и, следовательно, не должно ' t (и вы не должны пытаться получить доступ к той памяти, на которую он первоначально указывал). На самом деле, это довольно избыточно для начала, по крайней мере, в том, что касается видимого кода. Не имея другого использования, которое вы не демонстрируете, было бы чище иметь:

ctl = malloc( sizeof(uint64_t *) );
*ctl = malloc( *ctl_size * sizeof(uint64_t) );    

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

uint64_t *ctl_data = malloc(*ctl_size * sizeof(uint64_t));
...
csr_to_csrdu(..., ctl_size, &ctl_data, ...);
...
spmv_csrdu(..., ctl_size, ctl_data, ...);
...
free(ctl_data);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...