2016-11-16 10 views
0

行列式を乗算して演算子の優先順位などを追加できるようなプログラムを作成しようとしています。 私はプログラムを完了し、それは動作しますが、完了後にvalgrindにいくつかのエラーがあります。これは、次の行列へのポインタの近くでfree()の悪い使い方が原因であることは明らかです。しかし、私はそれを正しく行う方法を考え出すことができません。誰かが私を助けてください、私はそれに非常に感謝します。Valgrindブロックが失われ、どこから解放されますか?

は、ここに私のコードここ

#include <stdio.h> 
#include <stdlib.h> 
#include "files.h" 
struct MatrixObject *matrix; 


struct MatrixObject{ 
    size_t rows; 
    size_t columns; 
    int *numbers; 
    struct MatrixObject *pointToNext; 
    char sign; 
}; 

struct MatrixObject *newMatrixObject (size_t n, size_t m) { 

    struct MatrixObject *retVal = malloc (sizeof (struct MatrixObject)); 
    if (retVal == NULL) 
     return NULL; 

    retVal->numbers = malloc (n * m * sizeof (int*)); 
    if (retVal->numbers == NULL) { 
     free (retVal); 
     return NULL; 
    } 

    retVal->pointToNext = malloc(sizeof(struct MatrixObject*)); 
    if (retVal->pointToNext == NULL) { 
     free (retVal); 
     return NULL; 
    } 


    retVal->rows = n; 
    retVal->columns = m; 
    return retVal; 
} 

struct MatrixObject* getMatrixArray(){ 
    struct MatrixObject *object; 
    int m, n; 
    if(scanf("%d %d", &n, &m) != 2){ 
     errorHandle(); 
    } 
    if(n<0 || m<0){ 
     errorHandle(); 
    } 

    object = newMatrixObject(n, m); 
    for(int i = 0;i<n;i++){ 
     for(int j = 0;j<m;j++){ 
      if(fscanf(stdin, "%d", &(object->numbers[(i*m)+j]))!=1){ 
       errorHandle(); 
      } 
     } 
    } 

    char temp; 
    int res; 
    while((res=fscanf(stdin, "%c", &temp))!=EOF){ 
     if(res!=1){ 
      errorHandle(); 
     } 
     if(temp == '*' || temp == '+' || temp == '-'){ 
      object->sign = temp; 
      object->pointToNext = getMatrixArray(); 
      return object; 
     } 

    } 

    object->sign = 0; 
    object->pointToNext = 0; 
    return object; 
} 

void multiplyMatrix(struct MatrixObject *matrix1, struct MatrixObject *matrix2){ 
    int newColumns = matrix2->columns; 
    int newRows = matrix1->rows; 
    int* newNumbers = malloc(newColumns * newRows * sizeof(*newNumbers)); 
    int counter = 0; 
    if(matrix1->columns != matrix2->rows){ 
     errorHandle(); 
    } 


    for(int i = 0;i<newRows;i++){ 
     for(int k = 0;k<newColumns;k++){ 


      int sum = 0; 

      for(int j = 0;j<matrix1->columns;j++){ 
       sum+= ((matrix1->numbers)[(i*matrix1->columns)+j]) * ((matrix2->numbers)[(j*matrix2->columns)+k]); 
      }  
      newNumbers[counter] = sum; 
      counter++; 
     } 
    } 
    struct MatrixObject mat = *matrix2; 
    free(matrix2->numbers); 
    free(matrix2); 
    matrix1->pointToNext = mat.pointToNext; 
    matrix1->sign = mat.sign; 


    free(matrix1->numbers); 
    matrix1->numbers = newNumbers; 
    matrix1->columns = newColumns; 
    matrix1->rows = newRows; 

} 

void addMatrix(struct MatrixObject *matrix1, struct MatrixObject *matrix2, char sign){ 
    if(matrix1->columns != matrix2->columns || matrix1->rows != matrix2->rows){ 
     errorHandle(); 
    } 
    int columns = matrix1->columns; 
    int rows = matrix2->rows; 
    int* newNumbers = malloc(rows*columns*sizeof(*newNumbers)); 

    for(int i = 0;i<rows;i++){ 
     for(int j = 0;j<columns;j++){ 
      if(sign == '+'){ 
       newNumbers[i*columns + j] = matrix1->numbers[i*columns + j] + matrix2->numbers[i*columns + j]; 
      }else{ 
       newNumbers[i*columns + j] = matrix1->numbers[i*columns + j] - matrix2->numbers[i*columns + j]; 
      } 
     } 
    } 


    struct MatrixObject mat = *matrix2; 
    free(matrix2->numbers); 
    free(matrix2); 
    matrix1->pointToNext = mat.pointToNext; 
    matrix1->sign = mat.sign; 

    free(matrix1->numbers); 
    matrix1->numbers = newNumbers; 
} 


int main(int argc, char *argv[]) 
{ 

    struct MatrixObject *actualMatrix; 
    matrix = getMatrixArray(); 
    actualMatrix = matrix; 
    while(actualMatrix->pointToNext != 0){ 
     if(actualMatrix->sign == '*'){ 
      multiplyMatrix(actualMatrix, actualMatrix->pointToNext); 

     } 
     else{ 
      actualMatrix = actualMatrix->pointToNext; 
     } 
    } 

    printMatrix(matrix); 

    actualMatrix = matrix; 
    while(actualMatrix->pointToNext != 0){ 
     if(actualMatrix->sign == '+' || actualMatrix->sign == '-'){ 
      addMatrix(actualMatrix, actualMatrix->pointToNext, actualMatrix->sign); 
     } 
    } 

    printMatrix(matrix);  
    return 0; 
} 

は私valgrindのから出力される。ここで

==30650== 
==30650== HEAP SUMMARY: 
==30650==  in use at exit: 88 bytes in 6 blocks 
==30650== total heap usage: 17 allocs, 11 frees, 2,416 bytes allocated 
==30650== 
==30650== Searching for pointers to 6 not-freed blocks 
==30650== Checked 65,936 bytes 
==30650== 
==30650== 8 bytes in 1 blocks are definitely lost in loss record 1 of 6 
==30650== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==30650== by 0x400C59: newMatrixObject (main.c:32) 
==30650== by 0x400D0F: getMatrixArray (main.c:54) 
==30650== by 0x40133F: main (main.c:177) 
==30650== 
==30650== 8 bytes in 1 blocks are definitely lost in loss record 2 of 6 
==30650== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==30650== by 0x400C59: newMatrixObject (main.c:32) 
==30650== by 0x400D0F: getMatrixArray (main.c:54) 
==30650== by 0x400DC3: getMatrixArray (main.c:71) 
==30650== by 0x40133F: main (main.c:177) 
==30650== 
==30650== 8 bytes in 1 blocks are definitely lost in loss record 3 of 6 
==30650== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==30650== by 0x400C59: newMatrixObject (main.c:32) 
==30650== by 0x400D0F: getMatrixArray (main.c:54) 
==30650== by 0x400DC3: getMatrixArray (main.c:71) 
==30650== by 0x400DC3: getMatrixArray (main.c:71) 
==30650== by 0x40133F: main (main.c:177) 
==30650== 
==30650== 8 bytes in 1 blocks are definitely lost in loss record 4 of 6 
==30650== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==30650== by 0x400C59: newMatrixObject (main.c:32) 
==30650== by 0x400D0F: getMatrixArray (main.c:54) 
==30650== by 0x400DC3: getMatrixArray (main.c:71) 
==30650== by 0x400DC3: getMatrixArray (main.c:71) 
==30650== by 0x400DC3: getMatrixArray (main.c:71) 
==30650== by 0x40133F: main (main.c:177) 
==30650== 
==30650== LEAK SUMMARY: 
==30650== definitely lost: 32 bytes in 4 blocks 
==30650== indirectly lost: 0 bytes in 0 blocks 
==30650==  possibly lost: 0 bytes in 0 blocks 
==30650== still reachable: 56 bytes in 2 blocks 
==30650==   suppressed: 0 bytes in 0 blocks 
==30650== Reachable blocks (those to which a pointer was found) are not shown. 
==30650== To see them, rerun with: --leak-check=full --show-leak-kinds=all 
==30650== 
==30650== ERROR SUMMARY: 4 errors from 4 contexts (suppressed: 0 from 0) 

は、数直線のためのいくつかの情報です:

32: retVal->pointToNext = malloc(sizeof(struct MatrixObject*)); 
54: object = newMatrixObject(n, m); 
71: object->pointToNext = getMatrixArray(); 
177:matrix = getMatrixArray(); 
+2

'retVal->番号=のmalloc(N×m個の*のはsizeof(INT *))後newNumbersため割り当てるお勧めします;' - > 'retVal->番号=のmalloc(N×m個*ヒットメモリ割り当ての数は呼び出しの数と一致しなければなりません(sizeof(int)); retVal-> pointToNext = malloc(sizeof(struct MatrixObject *));-> 'retVal-> pointToNext = NULL; ' – BLUEPIXY

+0

現在はfree() 'よりも6つの割り当てがあります。問題を修正し、メモリリークがなくなります。 – user3629249

+0

@BLUEPIXYおかげでたくさんの人がいました。これを解決するにはもう数時間かかります。私はあなたに1つ借りています:) – shade254

答えて

0

私が見ることを最初はRETVALの数は、エラーチェックブロック内の空きはなかった

struct MtrixObject *newMatrixObject (size_t n, size_t m) { 

//... 

retVal->pointToNext = malloc(sizeof(struct MatrixObject*)); 
if (retVal->pointToNext == NULL) { 
    free (retVal); 
    return NULL; 
} 

です。構造体を解放すると、mallocで初期化された変数は解放されません。

あなたのメインマトリックスまたはactualMatrixは無料ではありませんでした。 デフォルトの行列actualMatrixを作成して編集してから、編集した行列を指すポインタpointToNextを設定しているようです。その後、actualMatrixをデフォルトのマトリックスに戻します。 (これはリンクされたリストなのでしょうか?)

これは、最後に無料ではない連鎖があることを意味します。おそらく試してみるはずです

struct MatrixObject *temp; 
while (matrix != NULL) { 
    temp = matrix.pointToNext; 
    free(matrix); 
    matrix = temp; 
} 

これは、最初の行列の後のすべての行列を通過して解放します。

printMatrixはあなたのコードにはなかったので、私はよく分かりません。そこに行列を自由にすることができます。

そして、もう一つの最後のコメント、あなたが方法でerrorHandleに()を呼び出しているので、多少の誤差がある場合は、ここではいくつかのmallocを

void multiplyMatrix(struct MatrixObject *matrix1, struct MatrixObject *matrix2){ 
    int newColumns = matrix2->columns; 
    int newRows = matrix1->rows; 
    int* newNumbers = malloc(newColumns * newRows * sizeof(*newNumbers)); 
    int counter = 0; 
    if(matrix1->columns != matrix2->rows){ 
     errorHandle(); 
    } 
//... 

を解放していない、errorHandleには、呼ばれた高い可能性があるが、無料のnewNumbersもあまりにもあなたのための方法はほとんどありません。それは決して参照として渡されませんでした。これはちょうど周りに浮遊し、きれいになることはありませんことを意味します。

IはerrorHandleに

+0

本当に貢献してくれてありがとう、実際には私の問題はretVal-> pointToNextの値をNULLに設定するだけで解決しました。しかし今、これらの他のすべての潜在的なエラーや悪い習慣を私のコードで見ることができます。私はあなたがそれを指摘してうれしいです、私は次のコードでそれを正しくしようとします。 – shade254

関連する問題