Valgrind leak of memory in a function that concatenates strings - c

I using valgrind to find a leak of memory. I wrote a function "prefix_to_string" to concatenate any two strings, but when I use the command
valgrind --leak-check=full ./helloworld
it says that I have a lot of leaks of memory. I really don't know where and why. I asked a friend why it was happening and he says that it was for doing malloc 2 times, 1 out the function and 1 in the function, but I don't know how to take care of that leak, because I think that I need to do those memory requests.
Here is the output that Valgrind gives me:
==9078== Memcheck, a memory error detector
==9078== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==9078== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==9078== Command: ./holamundo
==9078==
==9078== error calling PR_SET_PTRACER, vgdb might block
150:62
bye
==9078==
==9078== HEAP SUMMARY:
==9078== in use at exit: 63 bytes in 4 blocks
==9078== total heap usage: 5 allocs, 1 frees, 575 bytes allocated
==9078==
==9078== 5 bytes in 1 blocks are definitely lost in loss record 1 of 4
==9078== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9078== by 0x400740: prefix_to_string (in /mnt/c/Users/MrRaul/desktop/Tareas_edd/test_en_C/test_informales/holamundo)
==9078== by 0x4008AC: main (in /mnt/c/Users/MrRaul/desktop/Tareas_edd/test_en_C/test_informales/holamundo)
==9078==
==9078== 7 bytes in 1 blocks are definitely lost in loss record 2 of 4
==9078== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9078== by 0x400740: prefix_to_string (in /mnt/c/Users/MrRaul/desktop/Tareas_edd/test_en_C/test_informales/holamundo)
==9078== by 0x4008C3: main (in /mnt/c/Users/MrRaul/desktop/Tareas_edd/test_en_C/test_informales/holamundo)
==9078==
==9078== 8 bytes in 1 blocks are definitely lost in loss record 3 of 4
==9078== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9078== by 0x400740: prefix_to_string (in /mnt/c/Users/MrRaul/desktop/Tareas_edd/test_en_C/test_informales/holamundo)
==9078== by 0x4008D8: main (in /mnt/c/Users/MrRaul/desktop/Tareas_edd/test_en_C/test_informales/holamundo)
==9078==
==9078== 43 bytes in 1 blocks are definitely lost in loss record 4 of 4
==9078== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9078== by 0x400897: main (in /mnt/c/Users/MrRaul/desktop/Tareas_edd/test_en_C/test_informales/holamundo)
==9078==
==9078== LEAK SUMMARY:
==9078== definitely lost: 63 bytes in 4 blocks
==9078== indirectly lost: 0 bytes in 0 blocks
==9078== possibly lost: 0 bytes in 0 blocks
==9078== still reachable: 0 bytes in 0 blocks
==9078== suppressed: 0 bytes in 0 blocks
==9078==
==9078== For counts of detected and suppressed errors, rerun with: -v
==9078== ERROR SUMMARY: 4 errors from 4 contexts (suppressed: 0 from 0)
and here is the main of my code, so this way you can reproduce the problem:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <unistd.h>
#include <string.h>
#include <math.h>
char* prefix_to_string(char* first_string,char* second_string){
char* name = first_string;
char* extension = second_string;
char* name_with_extension;
name_with_extension = malloc(strlen(name)*(sizeof(char))+strlen(extension)*(sizeof(char))+1); /* make space for the new string (should check the return value ...) */
strcpy(name_with_extension, name); /* copy name into the new var */
strcat(name_with_extension, extension); /* add the extension */
return name_with_extension;
}
static char *itoa_simple_helper(char *dest, int i) {
if (i <= -10) {
dest = itoa_simple_helper(dest, i/10);
}
*dest++ = '0' - i%10;
return dest;
}
char *itoa_simple(char *dest, int i) {
char *s = dest;
if (i < 0) {
*s++ = '-';
} else {
i = -i;
}
*itoa_simple_helper(s, i) = '\0';
return dest;
}
int main(int argc, char *argv[]) {
int idx = 150;
int id = 62;
char str_idx[20];
char str_id[20];
itoa_simple( str_idx ,idx);
itoa_simple( str_id,id);
char *text_to_write;
text_to_write = malloc(2+sizeof(str_id)+sizeof(str_idx)+1);
text_to_write = prefix_to_string(str_idx,":");
text_to_write = prefix_to_string(text_to_write,str_id);
text_to_write = prefix_to_string(text_to_write,"\n");
printf("%s",text_to_write);
printf("bye\n");
free(text_to_write);
return 1;
}

You don't call free() often enough — you can't expect to avoid memory leaks if you don't call free() to release each separate memory allocation. And your repeated assignments to text_to_write in main() mean that you discard the only pointers to some of the allocated memory, so you can't free what was allocated. C requires endless care with memory management.
You have:
char *text_to_write;
text_to_write = malloc(2+sizeof(str_id)+sizeof(str_idx)+1);
// This assignment throws away the memory from the previous malloc
text_to_write = prefix_to_string(str_idx,":");
// This assignment throws away the memory from the previous prefix_to_string
text_to_write = prefix_to_string(text_to_write,str_id);
// This assignment also throws away the memory from the previous prefix_to_string
text_to_write = prefix_to_string(text_to_write,"\n");
printf("%s",text_to_write);
printf("bye\n");
// Calling free here only releases the last allocation from prefix_to_string
free(text_to_write);
You need something more like:
char *part1 = prefix_to_string(str_idx, ":");
char *part2 = prefix_to_string(part1, str_id);
char *part3 = prefix_to_string(part2, "\n");
printf("%s", part3);
printf("bye\n");
free(part1);
free(part2);
free(part3);

Related

Memory leak when using readline in joined or detached thread

For the past 2 hours or so, I have been trying to figure out why the following code throws a "possibly lost" memory leak:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <readline/readline.h>
#include <readline/history.h>
void *my_read(void* arg) {
char* buf;
if ((buf = readline(">> ")) != NULL) {
printf("Test\n");
if (strlen(buf) > 0) {
add_history(buf);
}
free(buf);
}
pthread_exit(0);
}
int main(int argc, char** argv) {
rl_catch_signals = 0;
pthread_t thread;
pthread_create(&thread, NULL, my_read, NULL);
pthread_join(thread, NULL);
return 0;
}
And I have also tried using detach instead of join, but the result is the same, which is:
==1498903== 272 bytes in 1 blocks are possibly lost in loss record 31 of 78
==1498903== at 0x4849C0F: calloc (vg_replace_malloc.c:1328)
==1498903== by 0x4012662: allocate_dtv (in /lib64/ld-linux-x86-64.so.2)
==1498903== by 0x401309D: _dl_allocate_tls (in /lib64/ld-linux-x86-64.so.2)
==1498903== by 0x497FAA4: pthread_create##GLIBC_2.34 (in /lib64/libc.so.6)
==1498903== by 0x10927B: main (in /home/user/readline)
I have also tried just straight up allocating memory and freeing it in a loop, which shows the same result.
EDIT: Picked the read -> my_read fix from Ajay, but the main issue still remains.
The main problem here is that you have defined a function named read. Readline internally calls the read function to read from stdin. This ends up recursively calling your read function leading to a stackoverflow and crashing your program. The crashed program doesn't free memory for the pthread_t state which should be done when you call pthread_join. This is the main reason valgrind complains.
A simple fix is to read --> my_read.
With the proposed fix the output of valgrind --leak-check=full on my end is -
==27167== Memcheck, a memory error detector
==27167== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==27167== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==27167== Command: ./test
==27167==
>> hello
Test
==27167==
==27167== HEAP SUMMARY:
==27167== in use at exit: 134,297 bytes in 195 blocks
==27167== total heap usage: 316 allocs, 121 frees, 155,633 bytes allocated
==27167==
==27167== LEAK SUMMARY:
==27167== definitely lost: 0 bytes in 0 blocks
==27167== indirectly lost: 0 bytes in 0 blocks
==27167== possibly lost: 0 bytes in 0 blocks
==27167== still reachable: 134,297 bytes in 195 blocks
==27167== suppressed: 0 bytes in 0 blocks
==27167== Reachable blocks (those to which a pointer was found) are not shown.
==27167== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==27167==
==27167== For counts of detected and suppressed errors, rerun with: -v
==27167== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

Memory leak in realloc of (void *) to concatenate string

Given a struct object with a void pointer (void *) value that is initialized using malloc to hold a string "chapt".
Afterwards, using realloc to make enough memory to concatenate another string.
/* Standard Imports */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
struct generic_type
{
void *value;
void (*add)(struct generic_type, int);
};
/* Function Declarations */
static void TestRun();
static void AddNumToString(struct generic_type element, int num);
#define TEST_ARRAY_SIZE 1
int main(int argc, char *argv[])
{
TestRun();
(void) argc;
(void) *argv;
return 0;
}
static void TestRun()
{
struct generic_type element;
element.value = malloc(sizeof(char) * 6);
assert (NULL != element.value);
element.value = strcpy(element.value, "chapt");
element.add = AddNumToString;
element.add(element, 10);
free(element.value);
}
static void AddNumToString(struct generic_type element, int num)
{
size_t num_length = snprintf(NULL, 0, "%d", num);
size_t str_length = strlen((char *)(element.value));
size_t new_length = str_length + num_length + 1;
char *num_string = (char *)malloc(sizeof(char) * (num_length + 1));
sprintf(num_string, "%d", num);
element.value = realloc(element.value, sizeof(char) * new_length);
assert (NULL != element.value);
element.value = strcat(((char *)(element.value)), num_string);
free(num_string);
}
This implementation results in the correct output but has a memory leak:
==29031== Memcheck, a memory error detector
==29031== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==29031== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==29031== Command: ./a.out
==29031==
==29031== Invalid free() / delete / delete[] / realloc()
==29031== at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==29031== by 0x1088EB: TestRun (teststructs.c:40)
==29031== by 0x108862: main (teststructs.c:22)
==29031== Address 0x522d040 is 0 bytes inside a block of size 6 free'd
==29031== at 0x4C31D2F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==29031== by 0x108999: AddNumToString (teststructs.c:52)
==29031== by 0x1088DF: TestRun (teststructs.c:39)
==29031== by 0x108862: main (teststructs.c:22)
==29031== Block was alloc'd at
==29031== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==29031== by 0x10887B: TestRun (teststructs.c:34)
==29031== by 0x108862: main (teststructs.c:22)
==29031==
==29031==
==29031== HEAP SUMMARY:
==29031== in use at exit: 8 bytes in 1 blocks
==29031== total heap usage: 3 allocs, 3 frees, 17 bytes allocated
==29031==
==29031== 8 bytes in 1 blocks are definitely lost in loss record 1 of 1
==29031== at 0x4C31D2F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==29031== by 0x108999: AddNumToString (teststructs.c:52)
==29031== by 0x1088DF: TestRun (teststructs.c:39)
==29031== by 0x108862: main (teststructs.c:22)
==29031==
==29031== LEAK SUMMARY:
==29031== definitely lost: 8 bytes in 1 blocks
==29031== indirectly lost: 0 bytes in 0 blocks
==29031== possibly lost: 0 bytes in 0 blocks
==29031== still reachable: 0 bytes in 0 blocks
==29031== suppressed: 0 bytes in 0 blocks
==29031==
==29031== For counts of detected and suppressed errors, rerun with: -v
==29031== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
It seems like the problem lies with the realloc line but I can't seem to see the problem with it.
Allocating enough memory during the initialization and avoiding realloc solves the problem but I rather know why this isn't working at this point.
AddNumToString is passed its element argument by value, so that it gets a copy of the object that was passed to it. This means that when you do
element.value = realloc(element.value, sizeof(char) * new_length);
the original pointer contained in the element is freed, but the new one is stored in the copy. The copy is lost when AddNumToString returns, so the newly allocated space is leaked. And worse, the object in the caller remains unchanged; in particular, it still contains the original pointer which has now been freed. So when it's eventually freed (not shown in your current code), that's a double free, which is bad.
You probably want to have AddNumToString take a pointer to struct generic_type instead, so that it can actually modify the object in place.

Memory leak at allocated/reallocted memory, "5 bytes in 1 blocks are definitely lost"

I'm getting a valgrind error when checking my program for memory leaks.
The error happens somewhere in my cutString function when allocating/reallocating memory, but I'm not sure what I'm doing wrong.
Am I allocating my memory incorrectly?
Here's the valgrind output:
$ valgrind --leak-check=full --track-origins=yes ./cutstring
==7017== Memcheck, a memory error detector
==7017== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==7017== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==7017== Command: ./cutstring
==7017==
Hell
==7017==
==7017== HEAP SUMMARY:
==7017== in use at exit: 5 bytes in 1 blocks
==7017== total heap usage: 3 allocs, 2 frees, 1,042 bytes allocated
==7017==
==7017== 5 bytes in 1 blocks are definitely lost in loss record 1 of 1
==7017== at 0x4839D7B: realloc (vg_replace_malloc.c:826)
==7017== by 0x109205: cutString (in cutstring)
==7017== by 0x109228: main (in cutstring)
==7017==
==7017== LEAK SUMMARY:
==7017== definitely lost: 5 bytes in 1 blocks
==7017== indirectly lost: 0 bytes in 0 blocks
==7017== possibly lost: 0 bytes in 0 blocks
==7017== still reachable: 0 bytes in 0 blocks
==7017== suppressed: 0 bytes in 0 blocks
==7017==
==7017== For counts of detected and suppressed errors, rerun with: -v
==7017== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
This is my code:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
char *cutString(char *str, char del)
{
char *new_string = (char*) malloc(strlen(str) * sizeof(char) + 1);
int i = 0;
while (str[i] != del)
{
new_string[i] = str[i];
i++;
}
new_string[i] = '\0';
new_string = (char*) realloc(new_string, strlen(new_string) + 1);
return new_string;
free(new_string);
}
int main()
{
printf("%s\n", cutString("Hello World!", 'o'));
return 0;
}
I'm guessing that I used realloc incorrectly, but I can't figure out why.
Some help would be appreciated, thanks!
cutString has to allocate memory and return it. Of course (and fortunately), all statements after an inconditional return aren't reached.
return new_string;
free(new_string); // never executed
}
Fortunately! because else you'd return unallocated memory: undefined behaviour.
The issue here is that you're passing the returned value to printf, but after that call, the pointer is lost. You have to store it to be able to free it, but only after having printed it.
int main()
{
char *s = cutString("Hello World!", 'o'));
printf("%s\n", s);
free(s);
return 0;
}
In C it's not possible to pipeline a function which allocates memory to printf without creating a memory leak. Other languages have garbage collectors or object destructors, but not C.

Valgrind complains when function returns char array pointer

I guess this is a newbie C question but I just could not find the answer. This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *copy(char *in) {
char *out = (char *) malloc(strlen(in)+1);
strcpy(out,in);
return out;
}
int main() {
char *orig = (char *) malloc(100);
strcpy(orig,"TEST");
printf("Original reads : %s\n",orig);
printf("Copy reads : %s\n",copy(orig));
}
It works fine, however valgrind --leak-check=yes complains:
==4701== Memcheck, a memory error detector
==4701== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==4701== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
==4701== Command: ./copy
==4701==
Original reads : TEST
Copy reads : TEST
==4701==
==4701== HEAP SUMMARY:
==4701== in use at exit: 105 bytes in 2 blocks
==4701== total heap usage: 2 allocs, 0 frees, 105 bytes allocated
==4701==
==4701== 5 bytes in 1 blocks are definitely lost in loss record 1 of 2
==4701== at 0x4C28C20: malloc (vg_replace_malloc.c:296)
==4701== by 0x400609: copy (in /root/alfred/copy)
==4701== by 0x40066C: main (in /root/alfred/copy)
==4701==
==4701== 100 bytes in 1 blocks are definitely lost in loss record 2 of 2
==4701== at 0x4C28C20: malloc (vg_replace_malloc.c:296)
==4701== by 0x400638: main (in /root/alfred/copy)
==4701==
==4701== LEAK SUMMARY:
==4701== definitely lost: 105 bytes in 2 blocks
==4701== indirectly lost: 0 bytes in 0 blocks
==4701== possibly lost: 0 bytes in 0 blocks
==4701== still reachable: 0 bytes in 0 blocks
==4701== suppressed: 0 bytes in 0 blocks
==4701==
==4701== For counts of detected and suppressed errors, rerun with: -v
==4701== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
Could someone please tell me what am I doing wrong? Thanks in advance!
You are malloc()'ing twice but do not free() them. Hence, valgrind complains about leaks.
Free the memory blocks you allocate and it should be fine.
char *p = copy(orig);
printf("Copy reads : %s\n", p);
free(orig);
free(p);
You are allocating memory block in the copy function, but never free it. So your code produces a memory leak, which is reported by the Valgrind. Correct version of your code should be
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *copy(char *in) {
char *out = malloc(strlen(in)+1);
//You need to check malloc result here!
strcpy(out,in);
return out;
}
int main() {
char *orig = (char *) malloc(100);
strcpy(orig,"TEST");
printf("Original reads : %s\n",orig);
char* copy = copy(orig);
printf("Copy reads : %s\n",copy);
free(orig);
free(copy);
return 0;
}
Also do not cast malloc() results.

Read in Words from Text File and Store into Dynamic Array Valgrind Errors in C

I'm trying to read in words from a text file in C using fscanf and putthem into a dynamically allocated array. However, I keep getting errors in Valgrind and (null) characters seem to be popping up in my output. I create a double pointer **str_array to hold each character array and initially allocate enough space for 4 character arrays. fscanf runs and stores the read in string into str[] and I use strcpy to copy str[]'s string into str_array. I realloc memory if str_array needs to hold more strings.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
char str[80];
int word_alloc = 0;
int word_count = 0;
char **str_array;
FILE *file;
file = fopen(argv[1], "r");
// Allocate memory to the array of strings (char arrays)
word_alloc = 4;
str_array = (char **) malloc(sizeof(char*) * word_alloc);
while (fscanf(file, "%s", str) != EOF) {
// If there are more than 4 strings, double size
if (word_count > word_alloc) {
word_alloc *= 2;
str_array = (char **) realloc(str_array, sizeof(char*) * word_alloc);
}
str_array[word_count] = (char *) malloc(sizeof(char) * (strlen(str) + 1));
strcpy(str_array[word_count], str);
++word_count;
}
int i = 0;
for (; i<word_count; i++) {
printf("Word: %s\n", str_array[i]);
}
i = 0;
for (; i<word_count; i++) {
free(str_array[word_count]);
}
free(str_array);
fclose(file);
return 0;
}
Here's the Valgrind error code.
==6254== Memcheck, a memory error detector
==6254== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==6254== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==6254== Command: ./a.out readin-test.txt
==6254==
==6254== Invalid write of size 8
==6254== at 0x4008A6: main (readin-test.c:25)
==6254== Address 0x51fc2e0 is 0 bytes after a block of size 32 alloc'd
==6254== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6254== by 0x400835: main (readin-test.c:16)
==6254==
==6254== Invalid read of size 8
==6254== at 0x4008C0: main (readin-test.c:26)
==6254== Address 0x51fc2e0 is 0 bytes after a block of size 32 alloc'd
==6254== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6254== by 0x400835: main (readin-test.c:16)
==6254==
==6254== Conditional jump or move depends on uninitialised value(s)
==6254== at 0x4C2BDA2: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6254== by 0x40094A: main (readin-test.c:37)
==6254== Uninitialised value was created by a heap allocation
==6254== at 0x4C2CE8E: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6254== by 0x400871: main (readin-test.c:22)
==6254==
==6254==
==6254== HEAP SUMMARY:
==6254== in use at exit: 999 bytes in 173 blocks
==6254== total heap usage: 181 allocs, 8 frees, 5,631 bytes allocated
==6254==
==6254== 999 bytes in 173 blocks are definitely lost in loss record 1 of 1
==6254== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6254== by 0x4008A5: main (readin-test.c:25)
==6254==
==6254== LEAK SUMMARY:
==6254== definitely lost: 999 bytes in 173 blocks
==6254== indirectly lost: 0 bytes in 0 blocks
==6254== possibly lost: 0 bytes in 0 blocks
==6254== still reachable: 0 bytes in 0 blocks
==6254== suppressed: 0 bytes in 0 blocks
==6254==
==6254== For counts of detected and suppressed errors, rerun with: -v
==6254== ERROR SUMMARY: 186 errors from 4 contexts (suppressed: 0 from 0)
You have an error in the free loop:
i = 0;
for (; i<word_count; i++) {
free(str_array[word_count]);
}
The array index should be i, not word_count.

Resources