2013-06-13 8 views
0

Я пишу функцию matlab mex с помощью кода c. У меня проблемы с освобождением выделенной памяти. У меня возникли проблемы со следующим кодом. Если я избавлюсь от всех бесплатных() строк, код работает, но у меня есть утечки памяти. Это означает, что код работает только несколько раз, прежде чем у меня закончится память. Все вызванные функции имеют указатели в качестве входных данных, поэтому я никогда не изменяю адрес указателя внутри функций. Я делаю ошибку в процедуре выделения/освобождения памяти?Динамическое распределение памяти и утечки памяти

void RLS_(int *M, int *N, double *h, double *y, double *P, double *theta) 
{ 

int i; 
double *Ph;//[*M]; 
double hPh; 
double inv; 
double *inv1; 
double *invPh;//[*M]; 
double *hTtheta;//[*N]; 
double *ymhTtheta;//[*N]; 
double **ADD;//[*M][*N]; 
double **invPhhT;//[*M][*M]; 
double **SUB;//[*M][*M]; 

Ph = (double *) malloc (*M * sizeof(double)); 
if (Ph == NULL) 
    return; 

invPh = (double *) malloc (*M * sizeof(double)); 
if (invPh == NULL) 
    return; 

hTtheta = (double *) malloc (*N * sizeof(double)); 
if (hTtheta == NULL) 
    return; 

ymhTtheta = (double *) malloc (*N * sizeof(double)); 
if (ymhTtheta == NULL) 
    return; 

ADD = (double **) malloc (*M * sizeof(double *)); 
if (ADD == NULL) 
    return; 
for (i=0;i<*M;i++) 
{ 
    ADD[i] = (double *) malloc(*N *sizeof(double)); 
    if (ADD[i] == NULL) 
     return; 
} 
invPhhT = (double **) malloc (*M * sizeof(double *)); 
if (invPhhT == NULL) 
    return; 
for (i=0;i<*M;i++) 
{ 
    invPhhT[i] = (double *) malloc(*M *sizeof(double)); 
    if (invPhhT[i] == NULL) 
     return; 
} 
SUB = (double **) malloc (*M * sizeof(double *)); 
if (SUB == NULL) 
    return; 
for (i=0;i<*M;i++) 
{ 
    SUB[i] = (double *) malloc(*M *sizeof(double)); 
    if (SUB[i] == NULL) 
     return; 
} 


matvectmult_(M,M,P,h,Ph);     

hPh = vectordot_(M,h,Ph);     

inv = 1/(1+hPh); inv1 =&inv; 

scalarmult_(M,inv1,Ph,invPh);    

vectmatmult_(M,N,theta,h,hTtheta);   

vectorsub_(N,y,hTtheta,ymhTtheta);   

vectvectmult_(M,N,invPh,ymhTtheta,*ADD);  

vectvectmult_(M,M,invPh,h,*invPhhT);  

matmulc_(M,M,M,*invPhhT,P,*SUB);   

// Update theta 
matrixadd_(M,N,theta,*ADD,theta); 

// Update P 
matrixsub_(M,M,P,*SUB,P);    

free(Ph); 
free(invPh); 
free(hTtheta); 
free(ymhTtheta); 
for (i=0;i<*M;i++) 
    free(ADD[i]); 
free(ADD); 
for (i=0;i<*M;i++) 
    free(invPhhT[i]); 
free(invPhhT); 
for (i=0;i<*M;i++) 
    free(SUB[i]); 
free(SUB); 
} 
+1

Я не вижу ничего связанного с MATLAB или MEX, это чистый C .. Возможно, вы можете использовать функции API MEX для выделения памяти, например ['mxMalloc'] (http://www.mathworks.com/help/matlab/apiref /mxcalloc.html) (который автоматически освобождается менеджером памяти MATLAB при выходе MEX-функции). – Amro

+0

Почему вы не используете 'mxMalloc' и' mxFree'? Вы используете «mex.h»? – horchler

+0

Потому что я не знал, что они существуют. Есть ли какая-либо польза для использования mxMalloc вместо malloc? – user2480446

ответ

0

Вот один момент - у вас есть много, много возвращаемых утверждений, и вы никогда не освобождаете память перед любым из этих вызовов. Например, если invPh является NULL, то память, выделенная для Ph, не будет выпущена.

+0

Хорошая точка в целом, но все эти ранние «возвращения» в этом конкретном коде попадают только в случае сбоя 'malloc', и в этом случае у него уже закончилась нехватка памяти, поэтому они вряд ли станут основной причиной утечка. –

0

Учитывая, что сказал @Owen, я бы поставил ваши операторы malloc в цикл do-while, который выполняется только один раз, и вместо этого замените все ваши операторы return на break.

do { 
    // mxMalloc 
    if (someVar[i] == NULL) 
     break; 

    // etc... 
    // The real meat of your code inside the do-while loop 
} while 0 == 1; 
// mxFree functions out here 

Я немного ржавый по кодированию mex-функций. Вероятно, для этого есть более эффективная практика, но это может помочь.

Возможно, вам также необходимо проверить, что каждая из переменных, которые вы пытаетесь освободить, также является != NULL, хотя функция free может сделать это автоматически.

EDIT: Изменил вышеуказанный код. Я думаю, что @horchler в комментариях сказал, что это лучше всего: вы должны использовать mxMalloc и mxFree вместо malloc и free.

+0

Здесь есть проблема. 'free (NULL)' по определению является no-op, поэтому нет причин проверять его. Однако, если вы используете эту логику do/while/break, в случае раннего 'break', любая из переменных, которые еще не получили выделение, будет иметь неинициализированное содержимое, поэтому вы можете в конечном итоге вызвать' free() ' на случайном указателе, который является неопределенным поведением (т.е., возможно, ошибкой памяти). Это, вероятно, не очень хороший подход, если не добавлены дополнительные охранники или инициализация. Альтернативой может быть факторизация освобождения от отдельной функции. –

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