The Problem
I was having some troubles with a library, wich makes use of flexible array members. There is no issues to allocate the object, but i can't reliably free it. Whenever the object has to be resized or free'd, using free() or realloc(), valgrind outputs errors of reads of uninitialized values, invalid free() calls, etc. I can't share the code, but i've managed to reduce the problematic context to the snippet below:
#include <stdlib.h>
#include <stdio.h>
char * rbuff(int len){
char * ptr = malloc(len);
return ptr;
}
void cfree(void * b){
free(*(char**)b);
}
void cbuff(void * b){
free(*(char**)b);
}
int main(){
char * g = rbuff(2);
cbuff(&g);
//cfree(&g);
return 0;
}
As it shows, there are two functions with the exact same code to free the object. The original code has lots of functions using free and realloc. All the functions receives and/or returns the object as a void pointer. Reducing it to two as in the snippet, i've observed an interesting undefined behavior. Using the function cbuff
, the output in valgrind is the following:
==6437== Memcheck, a memory error detector
==6437== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==6437== Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info
==6437== Command: ./main
==6437==
==6437==
==6437== HEAP SUMMARY:
==6437== in use at exit: 0 bytes in 0 blocks
==6437== total heap usage: 1 allocs, 1 frees, 2 bytes allocated
==6437==
==6437== All heap blocks were freed -- no leaks are possible
==6437==
==6437== For lists of detected and suppressed errors, rerun with: -s
==6437== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
There is no problem to free the object. However using cfree
the output is different, the free()
call is now invalid:
==6716== Memcheck, a memory error detector
==6716== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==6716== Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info
==6716== Command: ./main
==6716==
==6716== Invalid free() / delete / delete[] / realloc()
==6716== at 0x484447F: cfree (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6716== by 0x1093E7: main (in /mnt/c/Users/HOME/fd/fbgfbhdbgh/fd/main)
==6716== Address 0x1ffefffed0 is on thread 1's stack
==6716== in frame #1, created by main (???:)
==6716==
==6716==
==6716== HEAP SUMMARY:
==6716== in use at exit: 2 bytes in 1 blocks
==6716== total heap usage: 1 allocs, 1 frees, 2 bytes allocated
==6716==
==6716== 2 bytes in 1 blocks are definitely lost in loss record 1 of 1
==6716== at 0x4841888: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6716== by 0x109370: rbuff (in /mnt/c/Users/HOME/fd/fbgfbhdbgh/fd/main)
==6716== by 0x1093D7: main (in /mnt/c/Users/HOME/fd/fbgfbhdbgh/fd/main)
==6716==
==6716== LEAK SUMMARY:
==6716== definitely lost: 2 bytes in 1 blocks
==6716== indirectly lost: 0 bytes in 0 blocks
==6716== possibly lost: 0 bytes in 0 blocks
==6716== still reachable: 0 bytes in 0 blocks
==6716== suppressed: 0 bytes in 0 blocks
==6716==
==6716== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
==6716==
==6716== 1 errors in context 1 of 2:
==6716== Invalid free() / delete / delete[] / realloc()
==6716== at 0x484447F: cfree (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6716== by 0x1093E7: main (in /mnt/c/Users/HOME/fd/fbgfbhdbgh/fd/main)
==6716== Address 0x1ffefffed0 is on thread 1's stack
==6716== in frame #1, created by main (???:)
==6716==
==6716== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
I am not sure of why this is a thing, can someone explain this behavior and give thoughts on how to fix it ?
CodePudding user response:
cfree
is the name of a library function in Linux which is equivalent to free
. When you call cfree
in your code you actually end up calling this library function instead of the one in your code.
If you give this function some other name, the problem goes away.