2016-03-29 7 views
0

Ich habe eine Funktion in C geschrieben, die ich in eine Matlab ausführbare (mex-Datei). Die C-Funktion funktioniert einwandfrei, wenn sie einmal von der Matlab-Befehlszeile aus aufgerufen wird. Wenn sie jedoch in einer For-Schleife mehr als 1000 Mal aufgerufen wird, stürzt sie spontan ab. Dies geschieht auch dann, wenn ich bei jeder Iteration der for-Schleife die gleiche Eingabe füttere.Mex aus c-Code erstellt stürzt in Schleife, aber nicht, wenn einmal ausgeführt

Ich fürchte, ich habe einen lauernden C-Bug. ein Problem mit wiederholter Speicherzuweisung, aber ich weiß nicht genug c, um es zu beheben :(

Ich habe das Problem auf die WHILE-Schleife im folgenden Code eingegrenzt (wenn die ganze while-Schleife auskommentiert vor dem Kompilieren des Problems . weggeht) Bitte helfen

#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

Sie haben ein Speicherleck auf 'rigsOrigOrder', dass es nicht' free() 'ist. – LPs

+0

Verwenden Sie nicht 'puts' /' exit' verwenden Sie stattdessen 'mexErrMsgIdAndTxt'. Verwenden Sie auch 'mxCalloc' und' mxFree' anstelle von 'calloc' und' free'. – Amro

Antwort

1

an diesem Stück Code Werfen Sie einen Blick:

// // 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){ 

Sie tiesIdx Element für Raum Neuzuweisung, und ein wenig nach tiesIdx Position zugreifen möchten von der ties Array. Dies ist Undefined Behaviour wegen Ihrer Array 0-tiesIdx-1

Sie tiesIdx von 1 und dann auf dieser erhöht var eine Schleife ausführen inc Danach indiziert werden, das heißt Undefined Behaviour offensichtlich, weil Sie Indexfeld wird außerhalb der Grenzen.

Weiteren die innere Schleife:

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

ist die Überprüfung nicht für Arraygrenzen: wenn alle Elemente der Bindungen aufeinander folgend sind Sie werde des Arrays außerhalb der Grenzen.

HINWEIS: Sie haben eine Speicherleckage auf ranksOrigOrder, die es nicht free() ist.

Verwandte Themen