In my program I have used malloc()
and pointer but I did not use free()
to free those memory, I have compiled with -fsanitize=address
flag but it is saying there is no memory leaks. As far as I know if I allocate memory I also have to free the memory in the end of the program otherwise there will be memory leaks.
#include <stdio.h>
#include <stdlib.h>
void print2D(int rowSize, int **cols_size, int **arr) {
for(int i = 0; i < rowSize; i ) {
for(int j = 0; j < (*cols_size)[i]; j ) {
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
int** make2D(int rowSize, int **colSize) {
int** arr = (int**) malloc(sizeof(int*) * rowSize);
for(int i=0; i < rowSize; i ) {
arr[i] = (int*) malloc(sizeof(int) * 2);
}
*colSize = (int*) malloc(sizeof(int*) * 2);
(*colSize)[0] = 2;
(*colSize)[1] = 2;
arr[0][0] = 1;
arr[0][1] = 2;
arr[1][0] = 3;
arr[1][1] = 4;
return arr;
}
int main() {
int **colSize;
int rowSize = 2;
int** arr = make2D(rowSize, colSize);
print2D(rowSize, colSize, arr);
return 0;
}
I compiled and ran it with gcc -o wow -fsanitize=address wow.c && ./wow
How so there is no memory leaks? Am I missing something?
update
first time I compiled and ran using wsl (debian 10)
and fsanitize=address
failed to detect memory leaks
But when I compiled and ran with Arch 5.19
it detected DEADLYSIGNAL
. Now why is that?
CodePudding user response:
The compiler not only reports the leak (if the program manages to avoid a SIGSEGV) but that your program exhibits undefined behaviour.
$ gcc -Wall -Wextra -pedantic -fsanitize=address a.c -o a && ./a
a.c: In function ‘main’:
a.c:42:17: warning: ‘colSize’ is used uninitialized in this function [-Wuninitialized]
42 | int** arr = make2D(rowSize, colSize);
| ^~~~~~~~~~~~~~~~~~~~~~~~
1 2
3 4
=================================================================
==187==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 16 byte(s) in 1 object(s) allocated from:
#0 0x7fda63d72808 in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cc:144
#1 0x5594afb0c407 in make2D (/tmp/ikegami/a/a 0x1407)
#2 0x5594afb0c6d6 in main (/tmp/ikegami/a/a 0x16d6)
#3 0x7fda63a97082 in __libc_start_main ../csu/libc-start.c:308
Indirect leak of 16 byte(s) in 2 object(s) allocated from:
#0 0x7fda63d72808 in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cc:144
#1 0x5594afb0c433 in make2D (/tmp/ikegami/a/a 0x1433)
#2 0x5594afb0c6d6 in main (/tmp/ikegami/a/a 0x16d6)
#3 0x7fda63a97082 in __libc_start_main ../csu/libc-start.c:308
SUMMARY: AddressSanitizer: 32 byte(s) leaked in 3 allocation(s).
To fix the undefined behaviour, replace
int **colSize;
int rowSize = 2;
int** arr = make2D(rowSize, colSize);
print2D(rowSize, colSize, arr);
with
int *colSize;
int rowSize = 2;
int** arr = make2D(rowSize, &colSize);
print2D(rowSize, &colSize, arr);
Then you get
$ gcc -Wall -Wextra -pedantic -fsanitize=address a.c -o a && ./a
1 2
3 4
=================================================================
==249==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 16 byte(s) in 1 object(s) allocated from:
#0 0x7fd485c86808 in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cc:144
#1 0x55e3c49a8447 in make2D (/tmp/ikegami/a/a 0x1447)
#2 0x55e3c49a8797 in main (/tmp/ikegami/a/a 0x1797)
#3 0x7fd4859ab082 in __libc_start_main ../csu/libc-start.c:308
Direct leak of 16 byte(s) in 1 object(s) allocated from:
#0 0x7fd485c86808 in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cc:144
#1 0x55e3c49a84af in make2D (/tmp/ikegami/a/a 0x14af)
#2 0x55e3c49a8797 in main (/tmp/ikegami/a/a 0x1797)
#3 0x7fd4859ab082 in __libc_start_main ../csu/libc-start.c:308
Indirect leak of 16 byte(s) in 2 object(s) allocated from:
#0 0x7fd485c86808 in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cc:144
#1 0x55e3c49a8473 in make2D (/tmp/ikegami/a/a 0x1473)
#2 0x55e3c49a8797 in main (/tmp/ikegami/a/a 0x1797)
#3 0x7fd4859ab082 in __libc_start_main ../csu/libc-start.c:308
SUMMARY: AddressSanitizer: 48 byte(s) leaked in 4 allocation(s).
You should change print2D
to take const int *cols_size
instead of int **cols_size
. There's no need for the indirection.