2016-11-16 4 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-> чисел = таНос (п * т * SizeOf (INT *));' -> 'retVal-> числа = таНос (п * м * sizeof (int)); ',' retVal-> pointToNext = malloc (sizeof (struct MatrixObject *)); '->' retVal-> pointToNext = NULL; ' – BLUEPIXY

+0

количество распределений памяти кучи должно соответствовать количеству вызовов to 'free()' В настоящее время существует еще 6 распределений, чем есть 'free()' s Исправить эту проблему, и утечки памяти исчезнут – user3629249

+0

@BLUEPIXY Спасибо, много человек, это была утечка, которую я искал, вы спасли меня еще несколько часов решения этого. Я должен вам один :) – shade254

ответ

0

Первое, что я вижу

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

//... 

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

сосчитай RetVal никогда не был свободен в проверке блока ошибки. Помните, что освобождение структуры не освобождает какие-либо переменные внутри, которые были инициализированы malloc

В вашей основной матрице или actualMatrix не было бесплатно. Похоже, вы создаете матрицу по умолчанию, actualMatrix и редактируете ее, а затем устанавливаете указатель pointToNext, чтобы указать отредактированную матрицу. После этого вы устанавливаете фактическую матрицу обратно по умолчанию. (Является ли это LinkedList, который я вижу здесь?)

Это означает, что у вас есть цепочка матриц, которые не свободны в конце. Вероятно, вы должны попробовать

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

Это будет проходить через всю матрицу после этой первой матрицы и освобождать их.

Обратите внимание, что я понятия не имею, что делает printMatrix так, как никогда не было в вашем коде. Может быть, вы освобождаете там матрицы.

И последний комментарий, потому что вы звоните errorHandle() в методах, существует высокая вероятность того, если есть какая-то ошибка, вы не освободив некоторые mallocs

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 после errorHandle

+0

Большое спасибо за вклад, на самом деле моя проблема здесь была решена путем простого задания значения retVal-> pointToNext на NULL (как упоминалось выше).Но теперь я вижу все эти другие потенциальные ошибки и плохие практики в моем коде. Я рад, что вы это указали, я постараюсь сделать это правильно в своем следующем фрагменте кода. – shade254

Смежные вопросы