Valgrind сообщает о неверном чтении (и записи), но программа продолжает его выполнение - PullRequest
0 голосов
/ 28 мая 2019

Я пытаюсь решить одну из моих тренировок для экзамена в университете, но у меня застряла ошибка памяти, которую я не могу понять.Я должен выделить и инициализировать матрицу типа float, имеющую в качестве матрицы структуру с именем Mat.

typedef struct {
  int rows; 
  int cols;
  float **row_ptrs;
} Mat; 

. Для этого мне нужно написать функцию, которая возвращает адрес матрицы.Матрица должна быть массивом указателей на строки матрицы:

Mat* Mat_alloc(int rows, int cols){
        Mat* matrice = (Mat*)calloc(rows,sizeof(float**));
        float** righe = (float**)calloc(cols,sizeof(float*));
        (*matrice).row_ptrs=righe;
        (*matrice).rows=rows;
        (*matrice).cols=cols;
        *righe = (float*)malloc(sizeof(float));
        float* elem = *righe;
        Mat* sav_ptr = matrice; 
        int i,j;
        for(i=0;i<rows;i++){
            printf("questa e' la riga: %d con indirizzo: %x\n\n",i,righe);
            for(j=0;j<cols;j++){
                *elem = 0.0;
                printf("%f io sono l'elemento: %d con indirizzo: %x \n",*elem,j,elem);
                elem++;
                }
            printf("\n");
            righe++;
            j=0;
            }
        return sav_ptr;
    }

Также мне нужно освободить все после вызова и запуска функции, я написал эту функцию для этого:

void Mat_free(Mat *m){
    float** tofree = (*m).row_ptrs;
    free(*tofree);
    free(tofree);
    free(m);
    }

Когда я запускаю программу под valgrind после первого вывода на печать, я получаю это:

==6688== Memcheck, a memory error detector
==6688== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==6688== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==6688== Command: ./e1
==6688== 
Avvio Mat_alloc...

questa e' la riga: 0 con indirizzo: 4a4c4f0

0.000000 io sono l'elemento: 0 con indirizzo: 4a4c560 
==6688== Invalid write of size 4
==6688==    at 0x109311: Mat_alloc (in /home/sam/Scrivania/esercitazione 4 TDP/e1)
==6688==    by 0x1091FE: main (in /home/sam/Scrivania/esercitazione 4 TDP/e1)
==6688==  Address 0x4a4c564 is 0 bytes after a block of size 4 alloc'd
==6688==    at 0x483874F: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==6688==    by 0x1092BC: Mat_alloc (in /home/sam/Scrivania/esercitazione 4 TDP/e1)
==6688==    by 0x1091FE: main (in /home/sam/Scrivania/esercitazione 4 TDP/e1)
==6688== 
==6688== Invalid read of size 4
==6688==    at 0x109319: Mat_alloc (in /home/sam/Scrivania/esercitazione 4 TDP/e1)
==6688==    by 0x1091FE: main (in /home/sam/Scrivania/esercitazione 4 TDP/e1)
==6688==  Address 0x4a4c564 is 0 bytes after a block of size 4 alloc'd
==6688==    at 0x483874F: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==6688==    by 0x1092BC: Mat_alloc (in /home/sam/Scrivania/esercitazione 4 TDP/e1)
==6688==    by 0x1091FE: main (in /home/sam/Scrivania/esercitazione 4 TDP/e1)
==6688== 

Но тогда я не получаю сигнал sigsegv, и программа продолжает работать.Что я делаю не так?Я нашел это даже более странным, потому что free не генерирует никаких ошибок, и все блоки free'd.Ребята, у вас есть предложения?

Ее главная функция:

int main(int argc, char **argv) {
      /********************************************************
       *             TEST Mat_alloc/Mat_read                  *
       ********************************************************/
      printf("Avvio Mat_alloc...\n\n");
      Mat *m1 = Mat_alloc(5,5);
      float** try = (*m1).row_ptrs;
      printf("%f\n",**try);
      printf("fatto alloc\n");
      Mat_free(m1);
      printf("fatto free\n");

      return 0;
    }

1 Ответ

0 голосов
/ 28 мая 2019

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

Попробуйте это:

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

typedef struct {
    int rows;
    int cols;
    float **arr;
} Mat;

Mat* Mat_alloc(int rows, int cols){
    // memory allocation for struct Mat
    Mat* matrice = (Mat*)malloc(sizeof(Mat));
    // memory allocation for a given number of rows of our two-dimensional array
    matrice->arr = (float **)malloc(rows * sizeof(float *));
    int i = 0; int j = 0;
    // each row is a one-dimensional array, so we must allocate memory for each element
    for (i = 0; i < rows; ++i)
        matrice->arr[i] = (float *)malloc(cols * sizeof(float));

    (*matrice).rows=rows;
    (*matrice).cols=cols;

    for(i=0;i<rows; ++i){
        printf("questa e' la riga: %d con indirizzo: %p\n\n",i,&matrice->arr[i]);
        for(j=0;j<cols; ++j){
            matrice->arr[i][j] = j;
            printf("%f io sono l'elemento: %d con indirizzo: %p \n",matrice->arr[i][j],j,&matrice->arr[i][j]);
        }
        printf("\n");
    }
    return matrice;
}

void Mat_free(Mat *m){
    int i = 0;
    for(i=0;i< m->rows; ++i) {
        free(m->arr[i]);
    }

    free(m->arr);
    free(m);
}

int main(int argc, char **argv) {
    /********************************************************
     *             TEST Mat_alloc/Mat_read                  *
     ********************************************************/
    printf("Avvio Mat_alloc...\n\n");
    Mat *m1 = Mat_alloc(3,3);
    printf("fatto alloc\n");
    Mat_free(m1);
    printf("fatto free\n");

    return 0;
}
...