So I'm making a code that reads matrices and then does some counting with them.
I allocate memory to store the matrices in and fill it with more allocated arrays and free everything in the end, but Valgrind tells me I have a memory leak when I allocate a memory and then don't free it but when I do free it, the program doesn't work and I get SIGSEGV. It goes as follows:
int main() {
int ***arrMatrices= (int***) calloc(100, sizeof(int**));
char *operations = (char*) calloc(100, sizeof(char));
int heights[100], widths[100];
int noOfMatrices= 0, output = 0;
...
output = readMatrix(arrMatrices, &noOfMatrices, heights, widths);
...
freeEverything(arrMatrices,noOfMatrices,heights,widths,operations);
return (0);
}
int readMatrix(int ***arrMatrices, int *noOfMatrices, int *heights, int *widths){
int height, width;
int output = scanf("%d %d",&height, &width);
int result = 1;
...
int **matrix = (int**) calloc(height, sizeof(int*));
for(int i = 0; i < height; i++){
int *row = (int*) calloc(width, sizeof(int));
for(int y = 0; y < width; y++){
output = scanf("%d",(row+y));
if(output < 1) result = -1;
}
matrix[i] = row;
}
arrMatrices[*noOfMatrices] = matrix;
heights[*noOfMatrices] = height;
widths[*noOfMatrices] = width;
*noOfMatrices+=1;
return result;
}
void freeEverything(int ***arrMatrices, int noOfMatrices, int *heights, int *widths, char *operations){
for(int i = 0; i < noOfMatrices; i++){
for(int row = 0; row < heights[i]; row++){
free(arrMatrices[i][row]);
}
printf("%d\n",i);
free(arrMatrices[i]);
}
free(arrMatrices);
free(operations);
}
So the thing is I read the matrix, load it into my array and return. If I try to free it, I get an error, and apparently freeing it all in the end - row by row and matrix by matrix followed my the whole array - isn't enough. Valgrind specifically says that it's the matrix alloc in readMatrix
.
Can anyone tell me just how to do it right?
EDIT (added code + edits as per suggestions):
Here is another snippet of my code - of a following function that multiplies the matrices. There I declare the matrix the same way but I get no memory leak.
int multiply(int ***arrOfMatrices, int firstIndex, int secondIndex, int *heights, int *widths){
if(widths[firstIndex] != heights[secondIndex]) return -1;
int **matrix = (int**) calloc(heights[firstIndex],sizeof(int*));
for(int i = 0; i < heights[firstIndex]; i++){
int *row = (int*) calloc(widths[secondIndex], sizeof(int));
for(int y = 0; y < widths[secondIndex]; y++){
int sum = 0;
for(int j = 0; j < widths[firstIndex]; j++){
sum = sum + (arrOfMatrices[firstIndex][i][j] * arrOfMatrices[secondIndex][j][y]);
}
row[y] = sum;
}
matrix[i] = row;
}
arrOfMatrices[secondIndex] = matrix;
heights[secondIndex] = heights[firstIndex];
return 1;
}
EDIT 2 (posting the whole code):
#include <stdio.h>
#include <stdlib.h>
void printMatrix(int ***arrOfMatrices, int index, int *heights, int *widths){
int height = heights[index];
int width = widths[index];
printf("%d %d\n",height, width);
for(int i = 0; i < height; i++){
printf("%d",arrOfMatrices[index][i][0]);
for(int y = 1; y < width; y++){
printf(" %d",arrOfMatrices[index][i][y]);
}
printf("\n");
}
}
int readMatrix(int ***arrOfMatrices, int *noOfMatrices, int *heights, int *widths){
int height, width;
int output = scanf("%d %d",&height, &width);
int result = 1;
if(output < 2){
fprintf(stderr,"Error\n"); return 100;
}
int **matrix = (int**) calloc(height, sizeof(int*));
for(int i = 0; i < height; i++){
int *row = (int*) calloc(width, sizeof(int));
for(int y = 0; y < width; y++){
output = scanf("%d",(row+y));
if(output < 1) result = -1;
}
matrix[i] = row;
}
if(result == -1){
for(int i = 0; i < height; i++){
free(matrix[i]);
}
free(matrix);
return result;
}
arrOfMatrices[*noOfMatrices] = matrix;
heights[*noOfMatrices] = height;
widths[*noOfMatrices] = width;
*noOfMatrices+=1;
return result;
}
int multiply(int ***arrOfMatrices, int firstIndex, int secondIndex, int *heights, int *widths){
if(widths[firstIndex] != heights[secondIndex]) return -1;
int **matrix = (int**) calloc(heights[firstIndex],sizeof(int*));
for(int i = 0; i < heights[firstIndex]; i++){
int *row = (int*) calloc(widths[secondIndex], sizeof(int));
for(int y = 0; y < widths[secondIndex]; y++){
int sum = 0;
for(int j = 0; j < widths[firstIndex]; j++){
sum = sum + (arrOfMatrices[firstIndex][i][j] * arrOfMatrices[secondIndex][j][y]);
}
row[y] = sum;
}
matrix[i] = row;
}
arrOfMatrices[secondIndex] = matrix;
heights[secondIndex] = heights[firstIndex];
//free(matrix);
return 1;
}
int addSubstract(int ***arrOfMatrices, int firstIndex, int secondIndex, int *heights, int *widths, int modificator){
if(heights[firstIndex] != heights[secondIndex] || widths[firstIndex] != widths[secondIndex]) return -1;
for(int i = 0; i < heights[firstIndex]; i++){
for(int y = 0; y < widths[secondIndex]; y++){
arrOfMatrices[secondIndex][i][y] = (modificator * arrOfMatrices[secondIndex][i][y]) + arrOfMatrices[firstIndex][i][y];
}
}
return 1;
}
int countPriorityOperations(int ***arrOfMatrices, char *operations, int noOfMatrices, int *heights, int *widths){
/*
Picks all multiplications and counts 'em first
*/
int output;
for(int i = 0; i < noOfMatrices-1;i++){
if(operations[i] == '*'){
output = multiply(arrOfMatrices,i,i+1,heights,widths);
if(output == -1) return -1;
}
}
return 1;
}
int countRemainingOperations(int ***arrOfMatrices, char *operations, int noOfMatrices, int *heights, int *widths){
/*
Does all the other operations that aren't of the multiply masterrace
Skips matrices that have already been multiplied
*/
for(int i = 0; i < noOfMatrices-1;i++){
if(operations[i] == '*') continue;
if(operations[i] == '+' || operations[i] == '-'){
int modificator = 0;
if(operations[i] == '+') modificator = 1; else modificator = -1;
if(operations[i+1] != '*'){
if(addSubstract(arrOfMatrices,i, i+1, heights, widths, modificator) == -1) return -1;
}else{
if(addSubstract(arrOfMatrices,i, i+2, heights, widths, modificator) == -1) return -1;
++i;
}
}
}
return 1;
}
void freeEverything(int ***arrOfMatrices, int noOfMatrices, int *heights, int *widths, char *operations){
for(int i = 0; i < noOfMatrices; i++){
for(int row = 0; row < heights[i]; row++){
free(arrOfMatrices[i][row]);
}
free(arrOfMatrices[i]);
}
free(arrOfMatrices);
free(operations);
}
int main() {
int ***arrOfMatrices = (int***) calloc(100, sizeof(int**));
char *operations = (char*) calloc(100, sizeof(char));
int heights[100], widths[100];
int noOfMatrices = 0, output = 0;
while(output != EOF){
output = readMatrix(arrOfMatrices, &noOfMatrices, heights, widths);
if(output == -1){
fprintf(stderr,"Error\n"); return 100;
}
char temp;
output = scanf(" %c",&temp);
if(temp != '+' && temp != '-' && temp != '*' && output != EOF){
fprintf(stderr,"Error\n"); return 100;
}
if(output == EOF) break;
operations[noOfMatrices-1] = temp;
}
if(countPriorityOperations(arrOfMatrices,operations,noOfMatrices, heights, widths) == -1){
fprintf(stderr,"Error\n"); return 100;
}
if(countRemainingOperations(arrOfMatrices,operations,noOfMatrices, heights, widths) == -1){
fprintf(stderr,"Error\n"); return 100;
}
printMatrix(arrOfMatrices,noOfMatrices-1,heights,widths);
freeEverything(arrOfMatrices,noOfMatrices,heights,widths,operations);
return (0);
}
Valgrind output when all the inputs are correct and the program finishes correctly:
==24== HEAP SUMMARY:
==24== in use at exit: 72 bytes in 4 blocks
==24== total heap usage: 21 allocs, 17 frees, 1,244 bytes allocated
==24==
==24== 72 (24 direct, 48 indirect) bytes in 1 blocks are definitely lost in loss record 2 of 2
==24== at 0x4C2C9B4: calloc (vg_replace_malloc.c:711)
==24== by 0x400896: readMatrix (in [path])
==24== by 0x40109C: main (in [path])
==24==
==24== LEAK SUMMARY:
==24== definitely lost: 24 bytes in 1 blocks
==24== indirectly lost: 48 bytes in 3 blocks
==24== possibly lost: 0 bytes in 0 blocks
==24== still reachable: 0 bytes in 0 blocks
==24== suppressed: 0 bytes in 0 blocks
==24==
==24== For counts of detected and suppressed errors, rerun with: -v
==24== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)