Reputation: 315
Valgrind is saying that there is a memory leak, but I can't figure out what it is. I tried putting free's in the append function, freeing the string at the end of main and it still complains.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void append(char* string, char c)
{
int stringlength = strlen(string);
char* tmp = realloc(string, sizeof(char) * (stringlength + sizeof(char) + sizeof(char)));
if(tmp == NULL)
{
free(tmp);
free(string);
printf("Error appending character\n");
exit(1);
}
string = tmp;
string[stringlength] = c;
string[stringlength+1] = '\0';
}
int main()
{
char* string = malloc(sizeof(char));
string[0] = '\0';
printf("string before appending: %s\n", string);
append(string, 'c');
printf("string after appending: %s\n", string);
free(string);
return 0;
}
Here is the output from Valgrind: https://pastebin.com/dtXFm5YC (Its in Pastebin so Stack Overflow would actually let me post this question
Upvotes: 0
Views: 292
Reputation: 32596
Your main problems are not the memory leak but the invalid access :
Invalid read of size 1 ... Address 0x49d0028 is 0 bytes inside a block of size 1 free'd
and invalid free :
Invalid free() / delete / delete[] / realloc() ... Address 0x49d0028 is 0 bytes inside a block of size 1 free'd
because they have undefined behavior
when you do char* tmp = realloc(string, sizeof(char) * (stringlength + sizeof(char) + sizeof(char)));
that freed string coming from main, so when you printf it in main you access to a freed block. Note that the fact realloc freed the block is not mandatory
because you do not free tmp newly allocated by realloc in append you create your memory leak
then you free again string already freed by realloc
Also sizeof(char) * (stringlength + sizeof(char) + sizeof(char))
is strange, you have change sizeof(char)
is by definition 1, can be just stringlength + 2
You want that :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void append(char ** string, char c)
{
size_t stringlength = strlen(*string);
*string = realloc(*string, stringlength + 2);
if (*string == NULL)
{
fprintf(stderr, "cannot allocate memory\n");
exit(1);
}
(*string)[stringlength] = c;
(*string)[stringlength+1] = '\0';
}
int main()
{
char* string = malloc(1);
string[0] = '\0';
printf("string before appending: '%s'\n", string);
append(&string, 'c');
printf("string after appending: '%s'\n", string);
free(string);
return 0;
}
Compilation and execution :
pi@raspberrypi:/tmp $ gcc -g -pedantic -Wextra m.c
pi@raspberrypi:/tmp $ valgrind ./a.out
==17097== Memcheck, a memory error detector
==17097== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==17097== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==17097== Command: ./a.out
==17097==
string before appending: ''
string after appending: 'c'
==17097==
==17097== HEAP SUMMARY:
==17097== in use at exit: 0 bytes in 0 blocks
==17097== total heap usage: 3 allocs, 3 frees, 1,027 bytes allocated
==17097==
==17097== All heap blocks were freed -- no leaks are possible
==17097==
==17097== For counts of detected and suppressed errors, rerun with: -v
==17097== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)
Upvotes: 1