2013-08-15 19 views
8

このコードでメモリリークがどこで発生しているのかを見つけることができません。XSこのコードのメモリリーク?

基本的には、2次元配列を返すC関数のXSラッパーを記述したいと思います。

C-機能:

int CW_returnArray(double** arrayDouble, int* count) 
{ 
    int number = 10; 
    int index, index1; 
    for(index = 0; index < number; index++) 
    { 
     for(index1 = 0; index1 < 10000; index1++) 
     { 
      arrayDouble[index][index1] = 12.51; 
     } 

     count[index] = 10000; 
    } 
    return number; 
} 

array -> output param to hold the two dimensional array 
count -> output param to hold the number of element in each 1D array 

XSラッパー:

void 
returnArray() 
    PPCODE: 
    { 
    /** variable declaration **/ 
    double** array; 
    int i = 0, j=0, status; 
    int* count; 
    int totalArrays; 

    SV** SVArrays;  // to hold the references of 1D arrays 
    SV** SVtempArray; // temporary array to hold the elements of 1D array 

    /** allocate memory for C-type variables **/ 
    New(0, array, 10, double*); 

    for(i = 0; i<10;i++) 
    { 
     New(0, array[i], 10000, double); 
    } 

    New(0, count, 10, int); 

    /** call C function **/ 
    status = CW_returnArray(array, count); 

    /** check the status and retrieve the array to store it in stack **/ 
    if(status > 0) 
    { 
     totalArrays = status; 

     New(0, SVArrays, totalArrays, SV*); 
     for(i = 0; i<totalArrays; i++) 
     { 
      /** allocate memory for temporary SV array **/ 
      New(0, SVtempArray, count[i], SV*); 
      for(j = 0; j<count[i]; j++) 
      { 
       SVtempArray[j] = newSVnv(array[i][j]); 
      } 

      /** Make an array (AV) out of temporary SV array and store the reference in SVArrays **/ 
      SVArrays[i] = newRV_noinc((SV*) av_make(count[i], SVtempArray)); 

      /** free the memory allocated for temp SV array **/ 
      for(j = 0; j<count[i]; j++) 
      { 
       sv_free(SVtempArray[j]); 
      }    

      Safefree(SVtempArray); SVtempArray = NULL; 
     } 
    } 
    else 
    { 
     totalArrays = 0; 

    } 

    /** push the return values to stack **/ 
    EXTEND(SP, 2); 
    PUSHs(sv_2mortal(newSViv(status))); 
    PUSHs(sv_2mortal(newRV_noinc((SV*) av_make(totalArrays, SVArrays)))); 

    /** clean up allocated memory for SV "array of array" , if needed **/ 
    if(totalArrays > 0) 
    { 
     Safefree(SVArrays); SVArrays = NULL; 
    } 

    /** clean up allocated memory for C-type variables **/ 
    for(i = 0; i<10;i++) 
    { 
     Safefree(array[i]); 
    }  
    Safefree(array); array = NULL; 
    Safefree(count); count = NULL; 
} 

アン "アレイのアレイ" XSから返されます。 Perlスクリプトで

テスト:

for(1..100) 
{ 
    my ($status, $arrayref) = returnArray(); 
    undef $status; 
    $arrayref = []; 
    system('pause'); 
} 

機能returnArray()が呼び出されるたびに、Perlプロセスのコミットサイズが増加しています。 しかし、毎回$arrayref変数をガベージコレクションする必要があり、メモリ使用量を増やすべきではないと思います。

私は、XSで割り当てられたすべてのメモリを解放したいと思います。しかし、まだメモリリークがあります。 メモリリークのこのXSコードで何が問題になっていますか?

+0

あなたは 'newSVnv'を使って作成されたスカラの割り当てを解除しません。 'av_make'を使ってこれらのSVをすべてコピーするのではなく、あなた自身が配列を作成するようにcreateを割り当てる必要があります。 'newAV' +' av_extend' + 'av_fetch' – ikegami

+0

このコードはどうですか? '/ **一時SV配列に割り当てられたメモリを解放する**/ (j = 0; j InnovWelt

+0

決して 'sv_free'を呼び出さないでください。 'SvREFCNT_dec'を使用してください。 – ikegami

答えて

7

まあ、「テンプレートを解放し、その後、av_make()を行い、テンプレートの配列を作成する」のパターンが非常に良いではありません - あなたは、単にnewAV()であなたの配列を作成することにより、はるかに良いだろう、av_extend()右のサイズにそれをINGの各要素に対してav_store(newSVnv(...))を実行します。これにより、中間のSVtempArray割り振りを完全に回避できます。

しかし、これはあなたが尋ねたことではありません。私はあなたの問題は、あなたが最初にSafefree(SVArrays)を持たず、それぞれの要素がsv_free()であると思います。 av_make()重複ソース配列の内容は、あなたが

SVArrays[i] = newRV_noinc((SV*) av_make(count[i], SVtempArray)); 

によって作成された参照を漏洩しているAFAICTので、あなたはSVArraysを反復しSafefree(SVArrays)前に各要素に対してsv_free()を呼び出す必要があります。

+0

このコードで問題を指摘してくれてありがとうございます。 SVを解放するために 'sv_free()'が1つの場所( 'for j = 0; j InnovWelt

関連する問題