2

I write a code dealing with threads. compiling with -Wall gave me no errors. but when using valgrind with flags i see some unfreed allocating memory.

I tried using vgdb and valgrind, its pretty new to me. so i made some breakpoints and followed the code but didnt find any problem just when the program quits it shows the leaks summary.

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <valgrind/memcheck.h>
#include <valgrind/valgrind.h>


typedef struct Matrix{
    int **mat1;  
    int **mat2;
    int dim;
    int index;
}Matrix;

int **res;

void multMatrix(int** mat1, int** mat2, int** res, int dim, int col);
int resSpot(int** mat1, int** mat2, int row, int col, int matDim);
void matrixScan(int** mtrx, int size);
void matrixPrint(int** mtrx, int dim);
void* dealThread(void* column);
int ** allocArray(int dim);

/* function to calculate the position of the result(i,j) position */
int resSpot(int** mat1, int** mat2, int row, int col, int matDim){
    int sum=0, i;
    for (i=0; i<matDim; i++)
        sum+=mat1[row][i]*mat2[i][col];
    return sum;
}

/* Function to multiply matrix by column */
void multMatrix(int** mat1, int** mat2, int** result, int dim, int col){
    int i;
    for (i=0; i<dim; i++)
        result[i][col]= resSpot(mat1,mat2,i,col,dim);

}

//scan numbers for the matrix
void matrixScan(int** mtrx, int size){
    int i,j;
    for(i=0;i<size;i++)
        for(j=0;j<size;j++)
            scanf("%d",&mtrx[i][j]);
}

//print the matrix
void matrixPrint(int** mtrx, int dim){
    int i,j;
    for(i=0;i<dim;i++){
        for(j=0;j<dim;j++)
            printf("%d\t",mtrx[i][j]);
        printf("\n");
    }
}

//function for each thread to call mult matrix
void* dealThread(void* matPtr){

    Matrix* m=(Matrix*) matPtr;
    printf("index changes? %d \n", (*m).index);
    multMatrix((*m).mat1,(*m).mat2,res,(*m).dim,(*m).index);
    m=NULL;
    pthread_exit(0);

}

int ** allocArray( int dim){
    int i;//,j;
    int size=dim;
    int ** mat = malloc( size * sizeof(*mat));
    if (mat==NULL){
        perror("fail to malloc");
        exit(1);
    }
    for (i = 0; i < size; i++){
        mat[i] = malloc(size * sizeof(*(mat[i])));
        //mat[i]=realloc(mat[i], size*sizeof(int));
        if (mat[i]==NULL){
            perror("fail to malloc");
            exit(1);
        }   
      }
    return mat;
}

int main(){

    int **arr1, **arr2;
    int i,size; 

    printf("Enter MATRIX_DIM (number between 1 and 10)\n");
    scanf("%d",&size);

    pthread_t *thread;
    thread=malloc(sizeof(pthread_t)*size);

    arr1 = allocArray(size);
    arr2 = allocArray(size);
    res = allocArray(size);

    printf("Enter elements of first matrix\n");
    matrixScan(arr1,size);
    printf("Enter elements of second matrix\n");
    matrixScan(arr2,size);

    Matrix *matPtr;
    matPtr=(Matrix*)malloc(sizeof(Matrix)*size);
    if (matPtr==NULL){
        perror("fail to malloc\n");
        exit(1);
    }

    for(i=0;i<size ;i++){
        /* initialize the Matrix struct members to point the array
            and get the indexes */
        matPtr[i].mat1=arr1;
        matPtr[i].mat2=arr2;
        matPtr[i].dim=size;
        matPtr[i].index=i;

        if(pthread_create(&thread[i], NULL, dealThread , (void*) &matPtr[i]) <0){
            fputs("pthread create failed",stderr);
            exit(1);
        }

    }
    /*function to make it multi thread, wait till every thread finish  */
    for(i=0; i< size ; i++){
        pthread_join(thread[i], NULL);
    }

    printf("Product of the matrices:\n");
    matrixPrint(res,size);

    /*free the allocating */
    for( i = 0; i < size; i++){
        matPtr[i].mat1=NULL;
        matPtr[i].mat2=NULL;
        //matPtr[i].dim=NULL;
        //matPtr[i].index=NULL;
        free(arr1[i]);
        arr1[i]=NULL;
        free(arr1[i]);
        arr2[i]=NULL;
        free(res[i]);
        res[i]=NULL;


    }
    free(arr1);
    arr1=NULL;
    free(arr2);
    free(res);
    free(matPtr);
    matPtr=NULL;
    free(thread);
    thread=NULL;

    return 0;
}

==1298== HEAP SUMMARY:
==1298==     in use at exit: 1,714 bytes in 9 blocks
==1298==   total heap usage: 30 allocs, 21 frees, 3,610 bytes allocated
==1298== 
==1298== Searching for pointers to 9 not-freed blocks
==1298== Checked 112,600 bytes
==1298== 
==1298== 36 bytes in 1 blocks are still reachable in loss record 1 of 5
==1298==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==1298==    by 0x4009123: local_strdup (dl-load.c:162)
==1298==    by 0x4009123: _dl_map_object (dl-load.c:2509)
==1298==    by 0x4014A53: dl_open_worker (dl-open.c:235)
==1298==    by 0x400FFF3: _dl_catch_error (dl-error.c:187)
==1298==    by 0x40143BA: _dl_open (dl-open.c:661)
==1298==    by 0x518B0F1: do_dlopen (dl-libc.c:87)
==1298==    by 0x400FFF3: _dl_catch_error (dl-error.c:187)
==1298==    by 0x518B1B1: dlerror_run (dl-libc.c:46)
==1298==    by 0x518B1B1: __libc_dlopen_mode (dl-libc.c:163)
==1298==    by 0x4E47A42: pthread_cancel_init (unwind-forcedunwind.c:52)
==1298==    by 0x4E47C0B: _Unwind_ForcedUnwind (unwind-forcedunwind.c:129)
==1298==    by 0x4E45D3F: __pthread_unwind (unwind.c:129)
==1298==    by 0x4E40534: __do_cancel (pthreadP.h:280)
==1298==    by 0x4E40534: pthread_exit (pthread_exit.c:29)
==1298== 
==1298== 36 bytes in 1 blocks are still reachable in loss record 2 of 5
==1298==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==1298==    by 0x400BDC3: _dl_new_object (dl-object.c:165)
==1298==    by 0x4006783: _dl_map_object_from_fd (dl-load.c:1059)
==1298==    by 0x4008DFF: _dl_map_object (dl-load.c:2605)
==1298==    by 0x4014A53: dl_open_worker (dl-open.c:235)
==1298==    by 0x400FFF3: _dl_catch_error (dl-error.c:187)
==1298==    by 0x40143BA: _dl_open (dl-open.c:661)
==1298==    by 0x518B0F1: do_dlopen (dl-libc.c:87)
==1298==    by 0x400FFF3: _dl_catch_error (dl-error.c:187)
==1298==    by 0x518B1B1: dlerror_run (dl-libc.c:46)
==1298==    by 0x518B1B1: __libc_dlopen_mode (dl-libc.c:163)
==1298==    by 0x4E47A42: pthread_cancel_init (unwind-forcedunwind.c:52)
==1298==    by 0x4E47C0B: _Unwind_ForcedUnwind (unwind-forcedunwind.c:129)
==1298== 
==1298== 100 bytes in 5 blocks are definitely lost in loss record 3 of 5
==1298==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==1298==    by 0x400E93: allocArray (ex4.c:78)
==1298==    by 0x400F32: main (ex4.c:99)
==1298== 
==1298== 360 bytes in 1 blocks are still reachable in loss record 4 of 5
==1298==    at 0x4C2CC70: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==1298==    by 0x40118A2: _dl_check_map_versions (dl-version.c:293)
==1298==    by 0x4014EEC: dl_open_worker (dl-open.c:278)
==1298==    by 0x400FFF3: _dl_catch_error (dl-error.c:187)
==1298==    by 0x40143BA: _dl_open (dl-open.c:661)
==1298==    by 0x518B0F1: do_dlopen (dl-libc.c:87)
==1298==    by 0x400FFF3: _dl_catch_error (dl-error.c:187)
==1298==    by 0x518B1B1: dlerror_run (dl-libc.c:46)
==1298==    by 0x518B1B1: __libc_dlopen_mode (dl-libc.c:163)
==1298==    by 0x4E47A42: pthread_cancel_init (unwind-forcedunwind.c:52)
==1298==    by 0x4E47C0B: _Unwind_ForcedUnwind (unwind-forcedunwind.c:129)
==1298==    by 0x4E45D3F: __pthread_unwind (unwind.c:129)
==1298==    by 0x4E40534: __do_cancel (pthreadP.h:280)
==1298==    by 0x4E40534: pthread_exit (pthread_exit.c:29)
==1298== 
==1298== 1,182 bytes in 1 blocks are still reachable in loss record 5 of 5
==1298==    at 0x4C2CC70: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==1298==    by 0x400BB23: _dl_new_object (dl-object.c:75)
==1298==    by 0x4006783: _dl_map_object_from_fd (dl-load.c:1059)
==1298==    by 0x4008DFF: _dl_map_object (dl-load.c:2605)
==1298==    by 0x4014A53: dl_open_worker (dl-open.c:235)
==1298==    by 0x400FFF3: _dl_catch_error (dl-error.c:187)
==1298==    by 0x40143BA: _dl_open (dl-open.c:661)
==1298==    by 0x518B0F1: do_dlopen (dl-libc.c:87)
==1298==    by 0x400FFF3: _dl_catch_error (dl-error.c:187)
==1298==    by 0x518B1B1: dlerror_run (dl-libc.c:46)
==1298==    by 0x518B1B1: __libc_dlopen_mode (dl-libc.c:163)
==1298==    by 0x4E47A42: pthread_cancel_init (unwind-forcedunwind.c:52)
==1298==    by 0x4E47C0B: _Unwind_ForcedUnwind (unwind-forcedunwind.c:129)
==1298== 

and heres the leak

==1298== LEAK SUMMARY:
==1298==    definitely lost: 100 bytes in 5 blocks
==1298==    indirectly lost: 0 bytes in 0 blocks
==1298==      possibly lost: 0 bytes in 0 blocks
==1298==    still reachable: 1,614 bytes in 4 blocks
==1298==         suppressed: 0 bytes in 0 blocks
==1298== 
==1298== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
==1298== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

I really want to learn how to find where is the leak.

Thanks and appreciate for your time.

Try2prog
  • 161
  • 10
  • OT: regarding: `matPtr=(Matrix*)malloc(sizeof(Matrix)*size);` in C, the return type is `void*` which can be assigned to any pointer. Casting just clutters the code, making it more difficult to understand, debug, etc. – user3629249 Jun 09 '19 at 15:08
  • OT: regarding: `fputs("pthread create failed",stderr);` This does not tell the user why the problem occurred. Suggest using: `perror( "pthread create failed" )` as this will output to `stderr` both your error message and the text reason the system thinks the error occurred – user3629249 Jun 09 '19 at 15:12
  • when compiling, always enable the warnings, then fix those warnings. ( for `gcc`, at a minimum use: `-Wall -Wextra -Wconversion -pedantic -std=gnu11` ) Note: other compilers use different options to produce the same thing – user3629249 Jun 09 '19 at 15:15
  • amazing info thanks!. I get now these warning messages: ```warning: conversion to ‘long unsigned int’ from ‘int’ may change the sign of the result``` I think need to cast there, or change to unsigned int? it points me to the malloc places – Try2prog Jun 09 '19 at 15:55
  • 'malloc()` expects a `size_t` parameter. (I.E. long unsigned int) This is one of the reasons that the MAN page for each C library function needs to read/understood – user3629249 Jun 09 '19 at 23:58

1 Answers1

2
    free(arr1[i]);
    arr1[i]=NULL;
    free(arr1[i]);
    arr2[i]=NULL;
    free(res[i]);
    res[i]=NULL;

In this code you free arr1[i] twice when I think you mean to free arr2[i]. This is where the line 'by 0x400E93: allocArray (ex4.c:78)' comes from in valgrind. In general, when you see that, look at where you think you free the memory that is being malloc'd at line 78 and make sure that code is actually running and doing what you think it is.

NathanAck
  • 351
  • 3
  • 9
  • awsome man, thanks! I checked everywhere but there. do u know also whats the ```still reachable: 1,614 bytes in 4 blocks``` means? – Try2prog Jun 09 '19 at 14:32
  • https://stackoverflow.com/questions/3840582/still-reachable-leak-detected-by-valgrind gives a pretty good explanation of still reachable – NathanAck Jun 09 '19 at 14:43
  • last thing, its weird, one time when i run valgrind i get: /t``` total heap usage: 30 allocs, 30 frees, 3,610 bytes allocated``` and on the 2nd run without any changes i get ``` ==1886== in use at exit: 1,614 bytes in 4 blocks ==1886== total heap usage: 30 allocs, 26 frees, 3,610 bytes allocated``` is it related to the thread reachable thing? I really appreciate ur help thanks – Try2prog Jun 09 '19 at 14:56