How do I fix these memory leaks in C? - c

I am working on a function which allocates memory into an array, and then I free it later. Oddly enough, valgrind is giving me this error:
==93== HEAP SUMMARY:
==93== in use at exit: 11,160 bytes in 2,232 blocks
==93== total heap usage: 44,310 allocs, 42,078 frees, 1,632,230 bytes allocated
==93==
==93== 11,160 bytes in 2,232 blocks are definitely lost in loss record 1 of 1
==93== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==93== by 0x10976F: FillHashMap (in /mnt/c/Users/Jordan/Documents/GitHub/flwg/flwp)
==93== by 0x1092F1: main (in /mnt/c/Users/Jordan/Documents/GitHub/flwg/flwp)
==93==
==93== LEAK SUMMARY:
==93== definitely lost: 11,160 bytes in 2,232 blocks
==93== indirectly lost: 0 bytes in 0 blocks
==93== possibly lost: 0 bytes in 0 blocks
==93== still reachable: 0 bytes in 0 blocks
==93== suppressed: 0 bytes in 0 blocks
==93==
==93== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Dr. Memory is giving me a similar error:
Error #1: UNADDRESSABLE ACCESS: reading 0x0000000000000000-0x0000000000000008 8 byte(s)
# 0 testing [C:/Users/Jordan/Documents/GitHub/flwg/FLWP-2.c:120]
# 1 main [C:/Users/Jordan/Documents/GitHub/flwg/FLWP-2.c:105]
Note: #0:00:01.195 in thread 14704
Note: instruction: mov (%rax) -> %rax
The strcmp line of code is what causes it to break with Dr. Memory, although valgrind says I have issues even if I don't call this particular method.
void testing(struct wordConnections *header){
header = header->nextRow;
while(strcmp(header->word, "berk") != 0){
header = header->nextRow;
if(header == NULL){
printf("Failed");
return;
}
}
}
The code that runs is (the value and significance of numLetters + 1 is it is the length of the char* stored in the wordStorage, the value of numLetters is 4):
char** FillHashMap(struct wordConnections **(*HashMap)){
int h = 0;
/* The Amount of words in each file, File 1, 2, 3 */
int totalWordQuantity[3] = {132, 7420, 19829};
/*the word that we test, we add by two because first 4: word, 5th: \n, 6th: \0*/
char word[numLetters + 1];
/*how many times we've changed the character*/
int letterSpot = 0;
/*the character that goes through the file*/
char c;
FILE *flwd = OpenFile();
/* is it the first word of the line */
int wordCount = 0;
int isFirst = 1;
char p = fgetc(flwd);
c = p;
/* So, this is a temporary word, who will store the row, so all of its category folks will be contained within it */
char* rowWord = malloc(sizeof(char) * (numLetters + 1));
/*This stores all of the words*/
char** wordStorage = (char**)calloc(totalWordQuantity[numLetters - 2], sizeof(char*) * (numLetters + 1));
int i = 0;
/* First, take the character */
while((c = p) != EOF){
p = fgetc(flwd);
/* Add the character to the word */
word[letterSpot] = c;
/* Allows the letter spot to find the next place into the word */
letterSpot++;
/* Determines if the character is the placement immediately after the word */
if((c == ' ' && p != '\n') || c == '\n'){
letterSpot = 0;
/* Throws in the \0, converting into a string */
word[numLetters] = '\0';
wordStorage[wordCount] = malloc(sizeof(char) * (numLetters + 1));
h++;
strcpy(wordStorage[wordCount], word);
/* Determine if it's the first word */
if(isFirst == 1){
strcpy(rowWord, word);
/* Throw it in as a row */
AddRow2DLL(wordStorage[wordCount],
HashMap[FirstHashFunction(word[0])/*First Letter*/]
[SecondHashFunction(word)]/*First Vowel*/);
}
/* If it's not the first word */
else {
AddColumn2DLL(wordStorage[wordCount],
HashMap[FirstHashFunction(rowWord[0])/*First Letter*/]
[SecondHashFunction(rowWord)]/*First Vowel*/);
}
if(c == ' '){
isFirst = 0;
}
if(c == '\n'){
isFirst = 1;
}
wordCount++;
}
c = p;
}
free(rowWord);
fclose(flwd);
return wordStorage;
}
The hash map works fine, this is the method that causes the issues, without it, there are no memory leaks.
Later in the code, I free the wordStorage array with this method:
void FreeWordStorage(char** wordStorage){
int f = 0;
/* The Amount of words in each file, File 1, 2, 3 */
int totalWordQuantity[3] = {132, 7420, 19829};
int i;
for(i = 0; i < totalWordQuantity[numLetters - 2]; i++){
free(wordStorage[i]);
f++;
}
free(wordStorage);
}
I've tried all sorts of things to fix it. Oddly enough, when I check it with integers, I'm allocating and freeing the same amount of data.
Any help would be greatly appreciated. Thank you!

Valgrind's analysis indicates that the leaked memory was allocated by a bunch of malloc() calls by function FillHashMap(), and the only plausible candidate for those is this:
wordStorage[wordCount] = malloc(sizeof(char) * (numLetters + 1));
Function FreeWordStorage() appears to be correct for freeing the data allocated by FillHashMap(), so if some allocations are going unfreed then there are two main possibilities:
The pointer value returned by FillHashMap() is not later passed to FreeWordStorage(). The latter function might not be called at all on the code path that is being exercised, or perhaps a modified or outright wrong pointer is being passed to it.
Or,
Some or all of the pointers recorded in the allocated block returned by FillHashMap() are modified after being recorded, so that when it is called, FreeWordStorage() is ineffective at freeing the allocated memory.
Either one of those could be consistent with Dr. Memory's diagnostic, but whichever scenario applies, it does not appear to play out in the code presented in the question. I am reasonably confident that your pointers are being mangled somewhere else in the program.

Related

segmentation fault core dump error cache simulator

I am filling in code for a Cache simulator in C. How it work is you are given an input file with commands, you are to trace the results of that input simulating cache functions so that we can keep track of cache hits and misses. I have written the following code but seem to be having trouble with my ReplayTrace method. The line "accessData(addr)" throws a "segmentation fault (core dump)." I am aware that means I am trying to access something that I do not have permission to access or is no longer existing or is out of range. I have no idea how else to call this function. I am posting my whole code because I don't want to make assumptions about where the problem may lie. Can anyone tell where I am making a mistake?
/* TODO - COMPLETE THIS FUNCTION
* accessData - Access data at memory address addr.
* If it is already in cache, increase hit_count
* If it is not in cache, bring it in cache, increase miss count.
* Also increase eviction_count if a line is evicted.
*
* You will manipulate data structures allocated in initCache() here
* Implement Least-Recently-Used (LRU) cache replacement policy
*/
void accessData(mem_addr_t addr)
{
int i;
//pulling out the set and tag bits of address
mem_addr_t set = (addr >> b) & set_bits;
mem_addr_t tag = addr >> (s + b);
cache_set_t cache_set = cache[set];
/* judge if hit */
for (i = 0; i < E; ++i)
{
/* hit */
if (cache_set[i].valid && cache_set[i].tag == tag)
{
if (verbosity)
printf("hit ");
++hit_count;
/* update entry whose lru is less than the current lru (newer) */
for (int j = 0; j < E; ++j)
if (cache_set[j].valid && cache_set[j].lru < cache_set[i].lru)
++cache_set[j].lru;
cache_set[i].lru = 0;
return;
}
}
/* missed */
if (verbosity)
printf("miss ");
++miss_count;
/* find the biggest lru or the first invlaid line */
int j, maxIndex = 0;
unsigned long long maxLru = 0;
for (j = 0; j < E && cache_set[j].valid; ++j)
{
if (cache_set[j].lru >= maxLru)
{
maxLru = cache_set[j].lru;
maxIndex = j;
}
}
if (j != E)
{
/* found an invalid entry */
/* update other entries */
for (int k = 0; k < E; ++k)
if (cache_set[k].valid)
++cache_set[k].lru;
/* insert line */
cache_set[j].lru = 0;
cache_set[j].valid = 1;
cache_set[j].tag = tag;
}
else
{
/* all entry is valid, replace the oldest one*/
if (verbosity)
printf("eviction ");
++eviction_count;
for (int k = 0; k < E; ++k)
++cache_set[k].lru;
cache_set[maxIndex].lru = 0;
cache_set[maxIndex].tag = tag;
}
}
/* TODO - FILL IN THE MISSING CODE
* replayTrace - replays the given trace file against the cache
* reads the input trace file line by line
* extracts the type of each memory access : L/S/M
* YOU MUST TRANSLATE one "L" as a load i.e. 1 memory access
* YOU MUST TRANSLATE one "S" as a store i.e. 1 memory access
* YOU MUST TRANSLATE one "M" as a load followed by a store i.e. 2 memory accesses
* Ignore instruction fetch "I"
*/
void replayTrace(char* trace_fn)
{
char buf[1000];
mem_addr_t addr=0;
unsigned int len=0;
FILE* trace_fp = fopen(trace_fn, "r");
int count = 0;
if(!trace_fp){
fprintf(stderr, "%s: %s\n", trace_fn, strerror(errno));
exit(1);
}
while( fgets(buf, 1000, trace_fp) != NULL) {
if(buf[1]=='S' || buf[1]=='L' || buf[1]=='M') {
sscanf(buf+3, "%llx,%u", &addr, &len);
if(verbosity)
printf("%c %llx,%u ", buf[1], addr, len);
// TODO - MISSING CODE
// now you have:
// 1. address accessed in variable - addr
// 2. type of acccess(S/L/M) in variable - buf[1]
// call accessData function here depending on type of access
switch (buf[1])
{
case 'L':
case 'S':
accessData(addr);
++count;
break;
case 'M':
accessData(addr);
accessData(addr);
++count;
break;
default:
break;
}
if (verbosity)
printf("\n");
}
}
fclose(trace_fp);
}
--edit---
Valgrind output:
Command: ./csim -t traces/dave.trace -s 8 -E 4 -b 12
==4155737==
==4155737== Invalid read of size 8
==4155737== at 0x1095B2: accessData (csim.c:144)
==4155737== by 0x109AE3: replayTrace (csim.c:259)
==4155737== by 0x109DC6: main (csim.c:342)
==4155737== Address 0x4b9c040 is 0 bytes after a block of size 0 alloc'd
==4155737== at 0x483DD99: calloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==4155737== by 0x10938A: initCache (csim.c:99)
==4155737== by 0x109DB7: main (csim.c:336)
==4155737==
==4155737== Invalid read of size 1
==4155737== at 0x1095E2: accessData (csim.c:150)
==4155737== by 0x109AE3: replayTrace (csim.c:259)
==4155737== by 0x109DC6: main (csim.c:342)
==4155737== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==4155737==
==4155737==
==4155737== Process terminating with default action of signal 11 (SIGSEGV)
==4155737== Access not within mapped region at address 0x0
==4155737== at 0x1095E2: accessData (csim.c:150)
==4155737== by 0x109AE3: replayTrace (csim.c:259)
==4155737== by 0x109DC6: main (csim.c:342)
==4155737== If you believe this happened as a result of a stack
==4155737== overflow in your program's main thread (unlikely but
==4155737== possible), you can try to increase the size of the
==4155737== main thread stack using the --main-stacksize= flag.
==4155737== The main thread stack size used in this run was 8388608.
==4155737==
==4155737== HEAP SUMMARY:
==4155737== in use at exit: 472 bytes in 2 blocks
==4155737== total heap usage: 3 allocs, 1 frees, 4,568 bytes allocated
==4155737==
==4155737== LEAK SUMMARY:
==4155737== definitely lost: 0 bytes in 0 blocks
==4155737== indirectly lost: 0 bytes in 0 blocks
==4155737== possibly lost: 0 bytes in 0 blocks
==4155737== still reachable: 472 bytes in 2 blocks
==4155737== suppressed: 0 bytes in 0 blocks
==4155737== Rerun with --leak-check=full to see details of leaked memory
==4155737==
==4155737== For lists of detected and suppressed errors, rerun with: -s
==4155737== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
Segmentation fault (core dumped)```

How to lowercase an entire array of strings?

In the function below I must return a list of all duplicate strings in an hash table, ignoring cases if the parameter's value is equal to 1.
upo_strings_list_t upo_find_idup(const char **strs, size_t n, int ignore_case)
{
upo_strings_list_t list = NULL;
if(ignore_case) //Must lowercase each string of strs
{
size_t i;
size_t j;
size_t size = sizeof(char);
size_t len = 0;
char *aux = malloc(sizeof(char*)); //For each string of strs to lowercase
char **aux_strs = malloc(n * sizeof(char*)); //For store lowercase strings
assert( aux != NULL );
assert( aux_strs != NULL );
for(i = 0; i < n; ++i)
{
len = strlen(strs[i]) + 1;
aux_strs[i] = malloc(len * size);
strcpy(aux, strs[i]);
for(j = 0; aux[j] != '\0'; ++j)
{
aux[j] = tolower(aux[j]);
}
strcpy(aux_strs[i], aux);
}
list = upo_find_dup((const char**)aux_strs, n);
}
else
{
list = upo_find_dup(strs, n);
}
return list;
}
So, ignore case means that each string of strs must become lowercase. I tried to do that by a dynamic array of strings. When all strings are lowercase, the function calls another function (upo_find_dup) that returns a list of duplicate strings (for don't rewrite the same code).
upo_strings_list_t upo_find_dup(const char **strs, size_t n)
{
size_t i;
int val = 1;
upo_strings_list_t list = NULL;
upo_ht_linprob_t ht = upo_ht_linprob_create(UPO_HT_LINPROB_DEFAULT_CAPACITY,
upo_ht_hash_str_kr2e, upo_str_cmp);
assert( ht != NULL );
for(i = 0; i < n; ++i)
{
if(upo_ht_linprob_contains(ht, &strs[i]))
{
upo_strings_list_node_t *ln = malloc(sizeof(upo_strings_list_node_t));
if(ln == NULL)
{
perror("Unable to allocate memory for a new node");
abort();
}
ln->str = (char*)strs[i];
ln->next = list;
list = ln;
}
else
{
upo_ht_linprob_put(ht, &strs[i], &val);
}
}
return list;
}
And it seems work, because if I print every string saved in the list, they are exactly what they must be:
void test_find_idup()
{
const char *ary[] = {"One", "two", "four", "two", "one"};
size_t n = sizeof(ary) / sizeof(ary[0]);
//const char *res[] = {"one","two"};
upo_strings_list_t list;
list = upo_find_idup(ary, n, 1);
assert( list != NULL );
//size_t i = 0;
while(list != NULL)
{
printf("%s\n", list->str);
//assert( list->str == res[i] );
list = list->next;
//++i;
}
/* PRINT: one two :OK*/
}
But, when I try to assert if the string saved in the node of the list is equal to the result string (res[0] = "one" and res[1] = "two"), the assertion fail and a core dumped error appears:
test_hashtable_linprob: test_hashtable_linprob.c:1332: test_find_idup: Assertion `list->str == res[i]' failed.
==13842==
==13842== Process terminating with default action of signal 6 (SIGABRT)
==13842== at 0x4DEC18B: raise (raise.c:51)
==13842== by 0x4DCB858: abort (abort.c:79)
==13842== by 0x4DCB728: __assert_fail_base.cold (assert.c:92)
==13842== by 0x4DDCF35: __assert_fail (assert.c:101)
==13842== by 0x10E7E8: test_find_idup (test_hashtable_linprob.c:1332)
==13842== by 0x10EAF7: main (test_hashtable_linprob.c:1403)
==13842==
==13842== HEAP SUMMARY:
==13842== in use at exit: 901 bytes in 11 blocks
==13842== total heap usage: 234 allocs, 223 frees, 169,605 bytes allocated
==13842==
==13842== 13 bytes in 3 blocks are definitely lost in loss record 2 of 7
==13842== at 0x4A37ECB: malloc (vg_replace_malloc.c:307)
==13842== by 0x11029D: upo_find_idup (hashtable.c:593)
==13842== by 0x10E771: test_find_idup (test_hashtable_linprob.c:1324)
==13842== by 0x10EAF7: main (test_hashtable_linprob.c:1403)
==13842==
==13842== 424 (40 direct, 384 indirect) bytes in 1 blocks are definitely lost in loss record 6 of 7
==13842== at 0x4A37ECB: malloc (vg_replace_malloc.c:307)
==13842== by 0x10F482: upo_ht_linprob_create (hashtable.c:313)
==13842== by 0x110093: upo_find_dup (hashtable.c:546)
==13842== by 0x10E66D: test_find_dup (test_hashtable_linprob.c:1310)
==13842== by 0x10EAC1: main (test_hashtable_linprob.c:1398)
==13842==
==13842== 424 (40 direct, 384 indirect) bytes in 1 blocks are definitely lost in loss record 7 of 7
==13842== at 0x4A37ECB: malloc (vg_replace_malloc.c:307)
==13842== by 0x10F482: upo_ht_linprob_create (hashtable.c:313)
==13842== by 0x110093: upo_find_dup (hashtable.c:546)
==13842== by 0x11035A: upo_find_idup (hashtable.c:602)
==13842== by 0x10E771: test_find_idup (test_hashtable_linprob.c:1324)
==13842== by 0x10EAF7: main (test_hashtable_linprob.c:1403)
==13842==
==13842== LEAK SUMMARY:
==13842== definitely lost: 93 bytes in 5 blocks
==13842== indirectly lost: 768 bytes in 2 blocks
==13842== possibly lost: 0 bytes in 0 blocks
==13842== still reachable: 40 bytes in 4 blocks
==13842== suppressed: 0 bytes in 0 blocks
==13842== Reachable blocks (those to which a pointer was found) are not shown.
==13842== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==13842==
==13842== For lists of detected and suppressed errors, rerun with: -s
==13842== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)
Aborted (core dumped)
This is also the data structure:
/** \brief The type for nodes of list of strings. */
struct upo_strings_list_node_s {
char *str;
struct upo_strings_list_node_s *next;
};
/** \brief Alias for the type for nodes of list of strings. */
typedef struct upo_strings_list_node_s upo_strings_list_node_t;
/** \brief The type for list of strings. */
typedef upo_strings_list_node_t *upo_strings_list_t;
when I try to assert if the string saved in the node of the list is
equal to the result string (res[0] = "one" and res1 = "two"), the
assertion fail and a core dumped error appears
The fact that a core dump was produced is relevant only if you are inclined to load the dump into a debugger to examine the state of the program's memory when it aborted. Few people do that, and it is not uncommon for systems to be configured so that core dumps are not produced at all. I'll pay no further attention to it in this answer.
Many of your uses of assert() are inappropriate. Assertions are for run-time tests of the correctness of your code. They are useful for testing and documenting assumptions that your code makes about how other parts of your code will use it, or about characteristics the code relies upon the compiler to produce. Assertions must never contain code that you require to run on every execution of the program, such as tests for successful memory allocation, because they may be omitted from the executable completely depending on compile options. If one of your assertions fails, it always means that your code is buggy (possibly the assertion itself).
Write your own abort_unless() function or macro if you want a similar functionality for behavior that depends on input, runtime environment, or other behavior that may vary from run to run of the program.
Next, it looks like you're actually talking about this assertion, which is commented out in the code actually posted:
//assert( list->str == res[i] );
The test in that assertion has important differences from the one in your text, but I will focus on the one in the code. Possibly that particular use of assert is an appropriate one, so if it fails, then how is the code buggy? It is buggy because the == operator is comparing two char pointers themselves, not the data to which they point, and there is no reason for certainty that the two would be equal. You appear to want to employ strcmp(), instead:
assert(strcmp(list->str, res[i]) == 0);
Additionally, this code in upo_find_idup() ...
char *aux = malloc(sizeof(char*)); //For each string of strs to lowercase
... allocates enough space for a pointer itself, probably not more than 8 bytes. If you just wanted to store a pointer then there would be no need for the dynamic allocation or extra layer of indirection, but you're actually storing string contents. This will overrun the bounds of the allocated space if any of your strings are longer than a pointer.
Worse, your use of aux introduces unneeded extra work and code. It would be possible to allocate a long enough string for each case, but you're already doing that in the form of each aux_strs[i]. Just manipulate those directly.
Furthermore, the memory allocated for aux_strs itself is leaked, and so is the memory allocated for any of its members that are not carried through to the generated linked list. But this is also a bit of a logistical problem for you, because you must take care to avoid freeing the members that are carried through to the linked list. Furthermore, upo_find_dup() does not have enough information to do the freeing, because sometimes you call it with strings that it must not free in any case. A refactoring is probably needed here to enable you to manage memory correctly.
Try adding 32 to the ASCII value of each character, loops are the friends here.
Or you can use the built-in "toLower()" function.

Realloc Using Way too much Memory

I have made a minimal-working example of how to add elements to an array with realloc. This will be expanded in a future program that has many more elements.
#include <stdio.h>//printf
#include <stdlib.h>//malloc, realloc
int main() {
//BEGIN REALLOCATE-ABLE ARRAY
unsigned int *array, loop_variable;
const unsigned int ORIGINAL_ARRAY_SIZE = 4, REALLOC_INDICES = 99;
array = malloc(ORIGINAL_ARRAY_SIZE*sizeof(unsigned int));
for (loop_variable = 0; loop_variable < ORIGINAL_ARRAY_SIZE; loop_variable++) {
array[loop_variable] = loop_variable;
}
//BEGIN REALLOCATION
for (loop_variable = 1; loop_variable < REALLOC_INDICES; loop_variable++) {
array = realloc(array,sizeof(unsigned int)*(ORIGINAL_ARRAY_SIZE+loop_variable));
array[ORIGINAL_ARRAY_SIZE+loop_variable-1] = 2*(ORIGINAL_ARRAY_SIZE+loop_variable-1);
printf("reallocate array[%d] = %d\n",ORIGINAL_ARRAY_SIZE+loop_variable-1,array[ORIGINAL_ARRAY_SIZE+loop_variable-1]);
}
//BEGIN PRINTING ARRAY VALUES
for (loop_variable = 0; loop_variable < ORIGINAL_ARRAY_SIZE+REALLOC_INDICES-1; loop_variable++) {
printf("array[%d] = %d\n",loop_variable,array[loop_variable]);
}
//BEGIN FREE ARRAY
free(array); array = NULL;
return 0;
}
This should compile on any computer with gcc or clang. I then run this program on valgrind to ensure there are no memory leaks, and I get this:
==10791== HEAP SUMMARY:
==10791== in use at exit: 0 bytes in 0 blocks
==10791== total heap usage: 99 allocs, 99 frees, 20,988 bytes allocated
==10791==
==10791== All heap blocks were freed -- no leaks are possible
==10791==
==10791== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==10791== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
However, what troubles me is that I'm using 20,988 bytes for a 101-element array. The memory use grows exponentially as the array gets bigger, instead of linearly by 4 bytes/element.
If I'm understanding Valgrind's output correctly, this array should have 4*101 elements = 404 bytes memory size, but appears to use about 50 times as much memory as it should. This is a trivial problem for such a small program, but more meaningful programs will run out of memory on this computer.
My question: is this array really using 20,988 bytes, or is Valgrind double-counting the memory?
Is there a more memory-efficient way to do this? I can't understand other examples of realloc, though I have tried to follow them as closely as I can and make this question relevant to as many users as possible.
==10791== in use at exit: 0 bytes in 0 blocks
==10791== total heap usage: 99 allocs, 99 frees, 20,988 bytes allocated
is this array really using 20,988 bytes
No, it's using 0 bytes.
“allocated” obviously means “ever allocated”, including bytes that have been freed, since the amount of memory “still allocated” is zero (and another line tells you that).
The answer, thanks to user Pascal Cuoq, is that Valgrind will sum the memory allocations for every allocation. This is why I was confused, and thought that realloc was using too much memory.
I thought that if you want to find the size of the array, you can comment out the line that says
free(array); array = NULL;
to intentionally introduce a memory bug, and Valgrind will output
==11699== LEAK SUMMARY:
==11699== definitely lost: 408 bytes in 1 blocks
==11699== indirectly lost: 0 bytes in 0 blocks
==11699== possibly lost: 0 bytes in 0 blocks
==11699== still reachable: 0 bytes in 0 blocks
==11699== suppressed: 0 bytes in 0 blocks
==11699==
==11699== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
==11699== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
which gives you the true size of the array at its last iteration. There is probably a better way to do this, but my point is made.
I added improvements suggested by other users here. I had a very difficult time finding good, minimal working examples of realloc on search engines, and for future use of anyone finding this on a search engine, this is very basic minimal working example of a good, but probably not best, how to use realloc in C:
#include <stdio.h>//include printf function
#include <stdlib.h>//include malloc, realloc functions
int main() {
/*BEGIN REALLOCATE-ABLE ARRAY*/
unsigned int *array, loop_variable;
const unsigned int ORIGINAL_ARRAY_SIZE = 4, REALLOC_INDICES = 99999;
array = malloc(ORIGINAL_ARRAY_SIZE*sizeof(unsigned int));
for (loop_variable = 0; loop_variable < ORIGINAL_ARRAY_SIZE; loop_variable++) {
array[loop_variable] = loop_variable;
}
/*BEGIN REALLOCATION*/
for (loop_variable = 1; loop_variable < REALLOC_INDICES; loop_variable++) {
array = realloc(array,sizeof(unsigned int)*(ORIGINAL_ARRAY_SIZE+loop_variable));
if (array == NULL) {
printf("Array variable %d failed to reallocate :,-(\n",loop_variable);
exit(EXIT_FAILURE);
}
array[ORIGINAL_ARRAY_SIZE+loop_variable-1] = 2*(ORIGINAL_ARRAY_SIZE+loop_variable-1);
printf("reallocate array[%d] = %d\n",ORIGINAL_ARRAY_SIZE+loop_variable-1,array[ORIGINAL_ARRAY_SIZE+loop_variable-1]);
}
/*BEGIN PRINTING ARRAY VALUES*/
for (loop_variable = 0; loop_variable < ORIGINAL_ARRAY_SIZE+REALLOC_INDICES-1; loop_variable++) {
printf("array[%d] = %d\n",loop_variable,array[loop_variable]);
}
/*BEGIN FREE ARRAY*/
free(array); array = NULL;
return 0;
}

C freeing multi-dimensional array inside a struct seems incorrect

I've seen another question for allocating and freeing multi-dimensional arrays, but I suspect that it does not free correctly. For testing I made this small code extracted from my main code.
I compiled it under MacOS X.10 with XCode or gcc 4.9 with same results:
Faulty code
It runs 200000 times and the memory consumption grows up to 20GB!:
#include <stdlib.h>
typedef struct{
int lonSize;
int latSize;
double **grid;
}raf09_grid_t;
static raf09_grid_t raf09_grid;
void free_raf09_grid() {
if (raf09_grid.grid != NULL) {
int i;
for (i = 0; i < raf09_grid.lonSize; ++i) {
free(raf09_grid.grid[i]);
}
free(raf09_grid.grid);
}
raf09_grid.latSize = 0;
raf09_grid.lonSize = 0;
}
void get_raf09_grid() {
int nbElLat=381;
int nbElLon=421;
raf09_grid.grid = malloc(nbElLon*sizeof(double*));
int it;
for(it=0;it<nbElLon;it++)
raf09_grid.grid[it] = malloc(nbElLat*sizeof(double));
int i,j;
for(i=0;i<420;i++) {
for(j=0;j<380;j++) {
raf09_grid.grid[i][j]=0.0;
}
}
}
int main (int argc, char *argv[]) {
int i=0;
for (i=0;i<20000;i++) {
get_raf09_grid();
free_raf09_grid();
}
return 0;
}
I'm newbie so I suspect that my freeing is not correct...
Corrected code
With your help I corrected my code, it is now corrects and takes only 10M in ram:
#include <stdlib.h>
typedef struct{
int lonSize;
int latSize;
double **grid;
}raf09_grid_t;
static raf09_grid_t raf09_grid;
void free_raf09_grid() {
if (raf09_grid.grid != NULL) {
int i;
for (i = 0; i < raf09_grid.lonSize; ++i) {
free(raf09_grid.grid[i]);
}
free(raf09_grid.grid);
}
raf09_grid.latSize = 0;
raf09_grid.lonSize = 0;
}
void get_raf09_grid() {
raf09_grid.latSize=381;
raf09_grid.lonSize=421;
raf09_grid.grid = malloc(raf09_grid.lonSize*sizeof(double*));
int it;
for(it=0;it<raf09_grid.lonSize;it++)
raf09_grid.grid[it] = malloc(raf09_grid.latSize*sizeof(double));
int i,j;
for(i=0;i<420;i++) {
for(j=0;j<380;j++) {
raf09_grid.grid[i][j]=0.0;
}
}
}
int main (int argc, char *argv[]) {
int i=0;
for (i=0;i<20000;i++) {
get_raf09_grid();
free_raf09_grid();
}
return 0;
}
Valgrind is an invaluable tool in tracing memory leaks. Compiling your source code with debug information, and running it with:
valgrind --leak-check=full -v ./a.out
will give the following summary:
==7033== HEAP SUMMARY:
==7033== in use at exit: 1,283,208,000 bytes in 421,000 blocks
==7033== total heap usage: 422,000 allocs, 1,000 frees, 1,286,576,000 bytes allocated
==7033==
==7033== Searching for pointers to 421,000 not-freed blocks
==7033== Checked 92,040 bytes
==7033==
==7033== 18,288 bytes in 6 blocks are possibly lost in loss record 1 of 2
==7033== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7033== by 0x400611: get_raf09_grid (grid.c:27)
==7033== by 0x4006A8: main (grid.c:39)
==7033==
==7033== 1,283,189,712 bytes in 420,994 blocks are definitely lost in loss record 2 of 2
==7033== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7033== by 0x400611: get_raf09_grid (grid.c:27)
==7033== by 0x4006A8: main (grid.c:39)
==7033==
==7033== LEAK SUMMARY:
==7033== definitely lost: 1,283,189,712 bytes in 420,994 blocks
==7033== indirectly lost: 0 bytes in 0 blocks
==7033== possibly lost: 18,288 bytes in 6 blocks
==7033== still reachable: 0 bytes in 0 blocks
==7033== suppressed: 0 bytes in 0 blocks
==7033==
==7033== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 2 from 2)
--7033--
--7033-- used_suppression: 2 dl-hack3-cond-1
==7033==
==7033== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 2 from 2)
The link to line 27 shows that there is a problem with this statement:
raf09_grid.grid[it] = malloc(nbElLat*sizeof(double));
You are allocating more memory here than is being freed later in the program.
Update the raf09_grid.lonSize variable in get_raf09_grid() to equal nbElLon, and it fixes the problem.
In general, every malloc should have a corresponding free. Once you know which malloc is leaking, then you can find the code that is supposed to free that variable, and debug from there.
Note: I reduced the loop from 20000 to 1000, but it will give you the same information.
After reading through yoiur question, here are a few suggestions:
In the code:
for(i=0;i<420;i++) {
for(j=0;j<380;j++) {
raf09_grid.grid[i][j]=0.0;
}
you are looping i and j for 420 and 380, while you've defined :
int nbElLat=381;
int nbElLon=421;
So, you never process the 420th iteration for the Longitudes. The same with missing out on the 380th loop for Latitude.
If that's a desirable thing, its fine, else you should fix it to something like this:
for(i=0;i<nbElLon;i++) { //better use macros or variable names than just plain magic numbers
for(j=0;j<nbElLat;j++) {
raf09_grid.grid[i][j]=0.0;
}
Second, in your free_raf09_grid() function, you use:
for (i = 0; i < raf09_grid.lonSize; ++i) {
but you haven't initialized that variable anywhere.
Perhaps in function get_raf09_grid() just before the declaration of int i,j do this:
raf09_grid.lonSize = nbElLon;
raf09_grid.latSize = nbElLat;
The third important one.
In the lines below:
raf09_grid.grid = malloc(nbElLon*sizeof(double*));
int it;
for(it=0;it<nbElLon;it++)
raf09_grid.grid[it] = malloc(nbElLat*sizeof(double));
you should check if the mallocs have returned success or not aka check for NULL.
your for loop uses lonSize as a parameter, but it doesn't get updated anywhere

Valgrind complains while using realloc functions?

I have implemented my own version of strcat function.
It works fine but valgrind complains.
main()
{
char *src=NULL;
src=(char *) malloc(sizeof(char)*8);
strcpy(src,"sandeep");
xstrcat(src,"pathak");
printf("******FINAL STR IS : %s ********",src);
free(src);
src=NULL;
}
void xstrcat(char *src,const char *dest)
{
int dlen=strlen(dest);
int slen=strlen(src);
int j=0;
int i=0;
char *temp=(char *) realloc(src,(slen+dlen+1)*sizeof(char));
for(j=slen;i<dlen;i++,j++)
{
temp[j]=dest[i];
}
temp[j]='\0';
printf("%s",temp);
}
VALGRIND ERROR :
==31775== Invalid read of size 4
==31775== Invalid read of size 4
==31775== Invalid read of size 1
==31775== Invalid read of size 1
==31775== 14 bytes in 1 blocks are definitely lost in loss record 1 of 1
==31775== at 0x1B9053EE: realloc (vg_replace_malloc.c:197)
==31775== by 0x8048606: xstrcat (in /user/gur27268/Computer_Systems/Socket/DevTest/UTI
==31775== by 0x804850F: main (in /user/gur27268/Computer_Systems/Socket/DevTest/UTIL/a
==31775==
==31775== LEAK SUMMARY:
==31775== definitely lost: 14 bytes in 1 blocks.
==31775== possibly lost: 0 bytes in 0 blocks.
==31775== still reachable: 0 bytes in 0 blocks.
==31775== suppressed: 0 bytes in 0 blocks.
==31775== Reachable blocks (those to which a pointer was found) are not shown.**
==31775== To see them, rerun with: --show-reachable=yes
I have freed src, but using realloc tends to this problem...
Any help would be appreciated..
void xstrcat(char *src,const char *dest) {
You're passing src by value, and xstrcat is working on and modifying its local copy. Any changes you make to src will not be reflected in the calling function.
void xstrcat(char **src,const char *dest) {
// Work with *src
}
...
xstrcat(&src, ...)
This approach lets xstrcat modify main's src variable.
To quote a frequently mentioned sample:
void foo (int x) {
x = 2;
}
void bar (int * x) {
*x = 2;
}
int main() {
foo(9); // foo cannot modify the literal 9
int i = 1;
foo(i); // foo cannot modify the variable i
bar(&9); // This isn't legal - it can't be
bar(&i); // bar modifies i
}

Resources