试图解决可能的内存问题?

时间:2014-04-22 21:17:46

标签: c matrix

我在代码中运行了一个4x4矩阵。有时候我会得到正确的答案,有时我会得到一些正确的解决方案,剩下的就是奇怪的数字。例如,我的矩阵都是

1 2 3 4
1 2 3 4
1 2 3 4
1 2 3 4

我的解决方案应该是

10 20 30 40
10 20 30 40
10 20 30 40
10 20 30 40

但有时我会

10 20 30 40
10 20 30 40
10 20 20 20
10 20 30 40

我相信我有记忆问题,但我不确定如何修复它。我试过释放内存,但它并没有改变任何东西,但是,我本可以把它放在错误的地方。

继承我的代码

   #include <stdio.h>
   #include <stdlib.h>
   #include <pthread.h>

   //Create a typedef to pass vectors into the dot product
   typedef struct {
     int L;
     float *v1;
     float *v2;
  } dotVectors;



  //Prototype for the readMatrix method
  float** readMatrix(int *nRows, int *nCols,FILE* f);

  //Threaded dot product
  void* pDotProduct(void *p){
     //Recast the void pointer to a dotVectors pointer
     dotVectors *p1 = (dotVectors*) p;


     //Get all the stuff where the pointer is pointing
     int L = p1->L;
     float *v1 = p1->v1;
     float *v2 = p1->v2;

     float *sum = (float*)malloc(sizeof(float));

      //Do the dot product
      *sum=0;
      int i; for(i=0;i<L;i++){


         *sum+=v1[i]*v2[i];

     } free(v2);
      //Return the sum
      pthread_exit((void*)sum);


  }


  //Creates an empty matrix with r rows and c columns
  float** createFloatMatrix(int r, int c) {
    float** newMatrix =(float**)malloc(r*sizeof(float*));
    int i;
    for(i=0; i<c; i++) newMatrix[i]=(float*)malloc(c*sizeof(float));
    return newMatrix;
  }


  //Initializes a matrix with "value"
  void initMatrix(float **M, int r, int c, float value){
     int i,j;
     for (i=0; i<r; i++)
       for(j=0; j<c; j++)
          M[i][j]=value;
  }


  //Prints out a matrix with r rows and c columns
  void printMatrix(float** m, int r, int c) {
      int i,j;
     for(i=0;i<r;i++){
        for(j=0; j<c; j++){ printf("%g ", m[i][j]);}
        printf("\n");}

  }

  main() {
    float  **m1,**m2;
    int i,j,r1,c1,r2,c2;

    //Read in the first matrix from a file M1
    FILE* f;
    f=fopen("m1","r");

    //Reads the matrices from standard input - one file at a time
    m1 = readMatrix(&r1,&c1,f);
    fclose(f);


    //Read in a second matrix from a file M2
    f=fopen("m2","r");
    m2 = readMatrix(&r2,&c2,f);
    fclose(f);

    //*************//
    pthread_t t[r1][c2];

    //****************//
   //Create a dotVectors and fill it in
   int cr=c1; int rc; int k;

  for(i=0;i<r1;i++){
         for(j=0;j<c2;j++){
                 dotVectors *d= (dotVectors*)malloc(sizeof(dotVectors));
                 //Create a vector to store the jth column of the second matrix
                 float* temp = (float*)malloc(cr*sizeof(float));

                 for(k=0; k<cr; k++){ temp[k]=m2[k][j];}


                 d->L=c1;
                 d->v1=m1[i];
                 d->v2=temp;
                 rc = pthread_create(&t[i][j],NULL,pDotProduct,(void*)d);
                 }
         }

   //****************//
   void* dp;
   float** result=createFloatMatrix(r1,c2);
   //initMatrix(result, r1, c2, 0);
   for(i=0;i<r1;i++){
         for(j=0;j<c2;j++){
                 pthread_join(t[i][j],&dp);
                 result[i][j] = *((float*)dp);


                 }
         }printMatrix(result, r1,c2);
         pthread_exit(NULL);
         }

 //Read a matrix from a file f
   float** readMatrix(int *nRows, int *nCols, FILE* f) {
   int i=0;
   int j=0;
   int k=0;
   char c;
   *nRows=1; //The number of rows
   *nCols=1; //The number of columns
   float  nums[30][30];
   char* num;

   while(1) {

     //Read in the numbers on a row
     j=0; // j = the index of the number on the row - start at zero
     while(1) {

       //We will re-use the index i, so set to zero
       i=0;

       num = (char*)malloc(10*sizeof(char));

       //Read characters from standard input until a space or EOL
       while((c=getc(f))!=' ' && c!=10 && c!=EOF ) {
         num[i++]=c;
       }

       //Null terminate the array of characters
       num[i]=0;

       //Changes the array of characters to a float
       nums[k][j++]=atof(num);

       //If we are at the end of the line or end of file - break
        if( c==10 || c==EOF) break;

       //Set the number of numbers
       (*nCols)=j+1;
     }

     //Stop if you are at the end of file
     if (c==EOF) break;

     //Go to the next row
     k++;

    } //End while(1) outer loop
    *nRows=k;

    //Allocate memory for the row pointers
    float** retMat = (float**)malloc((*nRows)*sizeof(float*));
    //Allocate memory for the rows themselves
    for(i=0; i<(*nRows); i++) retMat[i]=(float*)malloc((*nCols)*sizeof(float));
    //Copy the nums matrix into the return matrix
    for(i=0; i<(*nRows); i++) for(j=0; j<(*nCols); j++) retMat[i][j]=nums[i][j];
    return retMat;

如果我在调试器中运行了大约20次,我会遇到一个在pthread_join ()中出现的分段错误。但我不明白它是怎么回事。有没有人对这个问题有任何建议或帮助?

1 个答案:

答案 0 :(得分:1)

我刚刚使用}编译了这个(在您的商家信息的末尾缺少gcc -g -lpthread),然后通过valgrind运行生成的可执行文件。它产生了很多错误(分配了内存但没有释放)但没有分段错误 - 输出是正确的。

我绝对建议在没有线程优先的情况下使其正常工作。你想重新考虑你的内存分配策略。例如,您可以一次创建一个内存块,然后创建一个指向它的指针数组。这就是Numerical Recipes in C的作用 - 它允许你&#34;假的&#34;可变长度的2D矩阵。对于每个create,您还需要free。并确保跟踪行与列。在用于创建rxc矩阵的原始代码中,您实际创建了cxc空格 - 所以如果您使用r>c调用它,那么您可能会遇到分段错误... < / p>

这样做的例子&#34;更好&#34;:

float** createFloatMatrix(int r, int c) {
  float** newMatrix =(float**)malloc(r*sizeof(float*));
  newMatrix[0] = malloc(r*c*sizeof (float) );
  for(i=1; i<r; i++) newMatrix[i]=newMatrix[0] + i*c;
  return newMatrix;
}

和相应的

void freeFloatMatrix(float** m) {
  free(m[0]); // this frees the whole block
  free(m);    // this frees the array of pointers
}

当然你的readMatrix函数正在做一些可怕的事情 - 它假设输入矩阵不能大于30x30但是没有测试以确保它保持在界限内;当您创建一个返回矩阵时,您不能使用自己的createFloatMatrix函数,......

最后 - 看起来你正以极其复杂的方式进行矩阵乘法。以下似乎可以做同样的事情,但是用更少的行。你有没有理由不这样做?

#include <stdio.h>
#include <stdlib.h>

//Prototypes
float** readMatrix(int *nRows, int *nCols,FILE* f);
void freeFloatMatrix(float**);

//Prints out a matrix with r rows and c columns
void printMatrix(float** m, int r, int c) {
  int i,j;
  for(i=0;i<r;i++) {
    for(j=0; j<c; j++) { 
      printf("%g ", m[i][j]);
    }
    printf("\n");
  }
}

// rewritten function for allocating float matrix:
float** createFloatMatrix(int r, int c) {
  int i;
  float** newMatrix =(float**)malloc(r*sizeof(float*));
  newMatrix[0] = malloc(r*c*sizeof (float) );
  for(i=1; i<r; i++) newMatrix[i]=newMatrix[0] + i*c;
  return newMatrix;
}

// need a function to free the matrix!!
void freeFloatMatrix(float** m) {
  free(m[0]); // this frees the whole block
  free(m);    // this frees the array of pointers
}


int main(void) {  // <<<< let's get the signature right...
float  **m1,**m2;
int i,j,r1,c1,r2,c2;

//Read in the first matrix from a file M1
FILE* f;
f=fopen("m1","r");
m1 = readMatrix(&r1,&c1,f);
fclose(f);

//Read in a second matrix from a file M2
f=fopen("m2","r");
m2 = readMatrix(&r2,&c2,f);
fclose(f);

// make sure that the dimensions match up:
if(c1 == r2) {
  float temp, **m3;
  int ii, jj, kk;
  m3 = createFloatMatrix(r1, c2);
  for(ii = 0; ii < r1; ii++) {
    for(jj = 0; jj < c2; jj++) {
      temp = 0;
      for(kk = 0; kk < c1; kk++) {
        temp += m1[ii][kk] * m2[kk][jj];
      }
      m3[ii][jj] = temp;
    }
  }
  printf("The product of the matrices is:\n");
  printMatrix(m3, r1, c2);
  freeFloatMatrix(m3);
  }
else printf("dimensions don't match!\n");
freeFloatMatrix(m2);
freeFloatMatrix(m1);
return 0;
}

//Read a matrix from a file f
float** readMatrix(int *nRows, int *nCols, FILE* f) {
  int i=0;
  int j=0;
  int k=0;
  char c;
  *nRows=1; //The number of rows
  *nCols=1; //The number of columns
  float  nums[30][30];
  char num[10];

 while(1) {
 //Read in the numbers on a row
   j=0; // j = the index of the number on the row - start at zero
   while(1) {
   //We will re-use the index i, so set to zero
     i=0;

     //Read characters from standard input until a space or EOL
     while((c=getc(f))!=' ' && c!=10 && c!=EOF && i < 10) {
       num[i++]=c;
     }

     //Null terminate the array of characters
     num[i]=0;

     //Changes the array of characters to a float
     nums[k][j++]=atof(num);

     //If we are at the end of the line or end of file - break
     if( c==10 || c==EOF || j == 30) break;

     //Set the number of numbers
     (*nCols)=j+1;
   }

   //Stop if you are at the end of file
   if (c==EOF) break;

   //Go to the next row
   k++;
   if (k == 30) break;
  } //End while(1) outer loop
  *nRows=k;

  //Allocate memory for the row pointers using the function we defined before
  float** retMat = createFloatMatrix(*nRows, *nCols);
  return retMat;
}

注意 - 还有很多其他地方可以改进这些代码...但是当你的条件良好的输入不超过你在代码中假定的大小时,至少上面会做矩阵乘法的好工作

一旦你说服自己这样做,你可以考虑在某种程度上添加线程 - 假设你的任务包括使这个代码多线程。我的个人方法是#include <omp.h>,只需在适当的位置添加#pragma omp for,但在多线程方面我就懒惰了。