2016-03-29 2 views
0

私はC言語で書かれた関数を使ってmatlabの実行可能ファイル(mexファイル)を作成しています。 C関数は、matlabのコマンドラインから一度呼び出すと正常に動作しますが、forループで1000回以上呼び出されると、自発的にクラッシュします。これは、forループの各繰り返しで同じ入力をフィードしても発生します。mexがCコードからループでクラッシュしましたが、一度だけ実行したときには動作しません。

私は潜んでいるc-バグがあります。いくつかの問題が繰り返しメモリを割り当てていますが、私はそれを修正するのに十分な知識はありません:(

私は問題をコンパイルする前に全体のwhileループがコメントアウトされている場合、以下のコードのWHILEループ。)消える助けてください

#include "mex.h" 
    #include <stdio.h> 
    #include <stdlib.h> 
    #include <math.h> 

    int sum_array(double a[], int from ,int to); 
    // to compile this code in matlab do: mex -v ranksort.c 

    void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){ 
      #define B_OUT  plhs[0] 
      #define A_IN  prhs[0] 

      int i,j,count,M,N; //declare some integers 
      double *list,*sort_list,*rank_idx,*sort_idx,*ranksOrigOrder;//declare some pointers to doubles which will be allocated dynamically 
      int *rank_list,*tielocs,*orig_indices; 

      //set values based on input: 
      M=mxGetM(A_IN);//get input row num 
      N=mxGetN(A_IN);//get input col num 
      if (M>N) 
       count=M; //get dimensions of A (columns...data must always be in columns) 
      else 
       count=N; 

      list =mxGetPr(A_IN); //grab data from pointer to inputted data 
      sort_list = calloc(count,sizeof(double)); //allocate size and fill w/zeros all my 'double' arrays 
      rank_idx =calloc(count,sizeof(double)); 
      sort_idx=calloc(count,sizeof(double)); 
      ranksOrigOrder=calloc(count,sizeof(double)); 
      tielocs =calloc(count+2,sizeof(double)); 
      orig_indices=calloc(count,sizeof(int)); //allocate size and fill w/ zeros all my 'int' arrays 
      rank_list =calloc(count,sizeof(int)); 

      if (sort_list==NULL||tielocs==NULL||rank_list==NULL||orig_indices==NULL||ranksOrigOrder==NULL||rank_idx==NULL||list==NULL){ puts ("Error (re)allocating memory"); exit (1); } 

      B_OUT = mxCreateDoubleMatrix(M, N, mxREAL); //create a matlab-style struct for output... 
      ranksOrigOrder = mxGetPr(B_OUT); // set in-code variable to its pointer 

      /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ CODE BODY STARTS HERE ~~~~~~~~~~~~~~~~~~~~*/ 
      /*Calculate the rank for each element in the arr_list*/ 
      for(i=0; i<count; i++){ 
       for(j=0; j<i; j++){ 
        if(list[i] >= list[j]) 
          rank_list[i]++; 
        else 
          rank_list[j]++; 
        } 
      } 

      for(i=0; i<count; i++){ 
       sort_list[rank_list[i]] = list[i]; 
       orig_indices[rank_list[i]] =i; 
       sort_idx[i]=i+1; 
      } 
      int tiesIdx=0; int *ties = NULL; 
      for (i=0; i<count-1;i++){ 
       if (sort_list[i]>= sort_list[i+1]){ 
       ties = (int*) realloc (ties, (tiesIdx) *sizeof(int));  //reallocate size of array 
       if (ties==NULL){ puts ("Error (re)allocating memory"); exit (1); } 
        ties[tiesIdx]=i; //add location of tie to newly grown array 
        tiesIdx++; //found a tie 
        } 
      } 
      // // append 2 after last element to ties 
      ties = (int*) realloc (ties, (tiesIdx) * sizeof(int));   

      //reallocate size of array 
      if (ties==NULL){ puts ("Error (re)allocating memory"); exit (1);   } 
      ties[tiesIdx]=count+1; 
      tiesIdx++; 

      int tiecount=0; //step thru all the found ties 

      // NO IN-LOOP CRASHING if this while loop is commented out.... 
      while (tiecount<tiesIdx){ 
       int tiestart =ties[tiecount]; //grab this tie to check if it is one of a pair or a member of an island of consecutives 
       int ntied=2; 

       while (ties[tiecount+1] == ties[tiecount] + 1){       //while it's a consecutive one... 
         tiecount++; 
         ntied++; 
       } 
       double mysum = (double)sum_array(sort_idx,tiestart,tiestart+ntied)/(double)ntied;   

       for (int t=tiestart; t<tiestart+ntied;t++){ 
         sort_idx[t]=mysum; 
        } 
       tiecount++; 
      } 

      for (i=0; i<count;i++){ 
       ranksOrigOrder[orig_indices[i]]=sort_idx[i]; 
      } 

      free(sort_list); 
      free(tielocs); 
      free(rank_list); 
      free(orig_indices); 
      free(rank_idx); 
      free(sort_idx); 
      return; 
    } 
    int sum_array(double a[], int from ,int to){ 
     int i, sum=0; 
     for (i=from; i<to; i++){ 
       sum = sum + (int)a[i]; 
     } 
     return(sum); 
    }  
+0

'ranksOrigOrder'のメモリリークは' free() 'ではありません。 – LPs

+0

'puts' /' exit'では 'mexErrMsgIdAndTxt'を使わないでください。また、 'calloc'と' free'の代わりに 'mxCalloc'と' mxFree'を使います。 – Amro

答えて

1

このコードの塊を見てみましょう!あなたがtiesIdx位置にアクセスしたい後

// // append 2 after last element to ties 
ties = (int*) realloc (ties, (tiesIdx) * sizeof(int)); 

//reallocate size of array 
if (ties==NULL){ puts ("Error (re)allocating memory"); exit (1);   } 
ties[tiesIdx]=count+1; 
tiesIdx++; 

int tiecount=0; //step thru all the found ties 

// NO IN-LOOP CRASHING if this while loop is commented out.... 
while (tiecount<tiesIdx){ 

はあなたが再割り当てtiesIdx要素のためのスペース、そして少しありますアレイ。あなたが範囲外のインデックス配列するため、これが原因で、あなたの配列のUndefined Behaviourですが、あなたが1でtiesIdxをincのその後0からtiesIdx-1

にインデックスを作成する必要がありますし、そのインクリメントVARにループを実行し、それは明らかにUndefined Behaviourです。

はさらに内部ループ:

 while (ties[tiecount+1] == ties[tiecount] + 1){       //while it's a consecutive one... 
       tiecount++; 
       ntied++; 
     } 

は、配列の境界をチェックされていません:絆のすべての要素が連続している場合は、範囲外のインデックス配列をよ。

注記ranksOrigOrderにメモリリークがあり、free()ではありません。

関連する問題