|
From: Robert C. <r.c...@gs...> - 2007-10-19 14:07:10
|
Hi, I have a string that I want to add words to a number of times in a
loop using asprintf (so that I don't need to worry about the length of
the resulting string), however I get complaints from valgrind about
memory leakage. I made a small test program shown below and compiled it
with the command line:
gcc -o0 -g -o testasprintf testasprintf.c
//testasprintf.c to test what happens to memory allocated using asprintf
#define _GNU_SOURCE
#include <stdio.h>
int main()
{
char *string;
asprintf(&string, "this is my string");
fprintf(stderr, "%s\n", string);
char *extension;
asprintf(&extension, "extended");
int i;
for(i=0; i<5; i++)
{
asprintf(&string, "%s %s", string, extension);
fprintf(stderr, "%s\n", string);
}
free(extension);
free(string);
return 0;
}
then ran:
valgrind --db-attach=yes --db-command="ddd %f %p" --leak-check=yes
./testasprintf
I got as output from valgrind:
==22456== Memcheck, a memory error detector.
==22456== Copyright (C) 2002-2007, and GNU GPL'd, by Julian Seward et al.
==22456== Using LibVEX rev 1732, a library for dynamic binary translation.
==22456== Copyright (C) 2004-2007, and GNU GPL'd, by OpenWorks LLP.
==22456== Using valgrind-3.2.3, a dynamic binary instrumentation framework.
==22456== Copyright (C) 2000-2007, and GNU GPL'd, by Julian Seward et al.
==22456== For more details, rerun with: -v
==22456==
this is my string
this is my string extended
this is my string extended extended
this is my string extended extended extended
this is my string extended extended extended extended
this is my string extended extended extended extended extended
==22456==
==22456== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 11 from 1)
==22456== malloc/free: in use at exit: 180 bytes in 5 blocks.
==22456== malloc/free: 14 allocs, 9 frees, 952 bytes allocated.
==22456== For counts of detected errors, rerun with: -v
==22456== searching for pointers to 5 not-freed blocks.
==22456== checked 59,784 bytes.
==22456==
==22456== 54 bytes in 1 blocks are definitely lost in loss record 1 of 2
==22456== at 0x401D5AB: realloc (vg_replace_malloc.c:306)
==22456== by 0x4092CBA: vasprintf (in /lib/tls/i686/cmov/libc-2.3.6.so)
==22456== by 0x407A3DD: asprintf (in /lib/tls/i686/cmov/libc-2.3.6.so)
==22456== by 0x8048461: main (testasprintf.c:19)
==22456==
==22456==
==22456== 126 bytes in 4 blocks are definitely lost in loss record 2 of 2
==22456== at 0x401D4B0: malloc (vg_replace_malloc.c:149)
==22456== by 0x4092CEA: vasprintf (in /lib/tls/i686/cmov/libc-2.3.6.so)
==22456== by 0x407A3DD: asprintf (in /lib/tls/i686/cmov/libc-2.3.6.so)
==22456== by 0x8048407: main (testasprintf.c:10)
==22456==
==22456== LEAK SUMMARY:
==22456== definitely lost: 180 bytes in 5 blocks.
==22456== possibly lost: 0 bytes in 0 blocks.
==22456== still reachable: 0 bytes in 0 blocks.
==22456== suppressed: 0 bytes in 0 blocks.
what I hoped asprintf would do is extend the memory for "string" and if
it had to move "string" to a different location in memory to get enough
space, it would free up the old memory, it seems this does not happen,
resulting in a memory leak.
If this is the case, the only way round I can see is this:
//testasprintf.c to test what happens to memory allocated using asprintf
#define _GNU_SOURCE
#include <stdio.h>
int main()
{
char *string;
asprintf(&string, "this is my string");
fprintf(stderr, "%s\n", string);
char *extension;
asprintf(&extension, "extended");
char *temp;
int i;
for(i=0; i<5; i++)
{
asprintf(&temp, "%s %s", string, extension);
free(string);
asprintf(&string, "%s", temp);
free(temp);
fprintf(stderr, "%s\n", string);
}
free(extension);
free(string);
return 0;
}
which gives as output:
==23550== Memcheck, a memory error detector.
==23550== Copyright (C) 2002-2007, and GNU GPL'd, by Julian Seward et al.
==23550== Using LibVEX rev 1732, a library for dynamic binary translation.
==23550== Copyright (C) 2004-2007, and GNU GPL'd, by OpenWorks LLP.
==23550== Using valgrind-3.2.3, a dynamic binary instrumentation framework.
==23550== Copyright (C) 2000-2007, and GNU GPL'd, by Julian Seward et al.
==23550== For more details, rerun with: -v
==23550==
this is my string
this is my string extended
this is my string extended extended
this is my string extended extended extended
this is my string extended extended extended extended
this is my string extended extended extended extended extended
==23550==
==23550== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 11 from 1)
==23550== malloc/free: in use at exit: 0 bytes in 0 blocks.
==23550== malloc/free: 24 allocs, 24 frees, 1,677 bytes allocated.
==23550== For counts of detected errors, rerun with: -v
==23550== All heap blocks were freed -- no leaks are possible.
Is there a neater/better way to do this?
Thanks,
Rob.
|
|
From: Olly B. <ol...@su...> - 2007-10-19 14:15:56
|
On 2007-10-19, Robert Cussons <r.c...@gs...> wrote:
> what I hoped asprintf would do is extend the memory for "string" and if
> it had to move "string" to a different location in memory to get enough
> space, it would free up the old memory, it seems this does not happen,
> resulting in a memory leak.
This isn't really valgrind-related.
As documented, a call to asprintf() allocates memory to hold the string.
You need to free that memory when you're done with it or you'll leak it.
Cheers,
Olly
|
|
From: Christoph B. <bar...@or...> - 2007-10-19 14:29:38
|
> what I hoped asprintf would do is extend the memory for "string" and if
> it had to move "string" to a different location in memory to get enough
> space, it would free up the old memory, it seems this does not happen,
> resulting in a memory leak.
> If this is the case, the only way round I can see is this:
Yes asprintf does not release memory.
> for(i=0; i<5; i++)
> {
> asprintf(&temp, "%s %s", string, extension);
> free(string);
> asprintf(&string, "%s", temp);
> free(temp);
> fprintf(stderr, "%s\n", string);
> }
You could use:
asprintf(&temp, "%s %s", string, extension);
free(string);
string = temp;
Christoph
|
|
From: Robert C. <r.c...@gs...> - 2007-10-19 14:32:25
|
Christoph Bartoschek wrote:
>> what I hoped asprintf would do is extend the memory for "string" and if
>> it had to move "string" to a different location in memory to get enough
>> space, it would free up the old memory, it seems this does not happen,
>> resulting in a memory leak.
>> If this is the case, the only way round I can see is this:
>
> Yes asprintf does not release memory.
>
>> for(i=0; i<5; i++)
>> {
>> asprintf(&temp, "%s %s", string, extension);
>> free(string);
>> asprintf(&string, "%s", temp);
>> free(temp);
>> fprintf(stderr, "%s\n", string);
>> }
>
> You could use:
>
> asprintf(&temp, "%s %s", string, extension);
> free(string);
> string = temp;
>
Of course, must be Friday :-)
Thanks once again Christoph.
|