Valgrind shows more memory allocated than actually is - c

I was writting some simple code in C to test some memory allocation and pointers:
#include <stdlib.h>
#include <stdio.h>
int *randomAlloc(int n) {
int *address = NULL, i = 0;
address = malloc (n * sizeof(int));
for (i = 0; i < n ; i++){
*(address + i) = i ;
}
return address;
}
int main(int argc, char* argv[] ) {
int *address;
int n;
printf("Type vector size: ");
scanf("%d", &n);
address = randomAlloc(n);
free(address);
}
Yet for some reason when I type 4 as input valgrind outputs:
==2375== Memcheck, a memory error detector
==2375== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==2375== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==2375== Command: ./a.out
==2375==
Type vector size: 4
==2375==
==2375== HEAP SUMMARY:
==2375== in use at exit: 0 bytes in 0 blocks
==2375== total heap usage: 3 allocs, 3 frees, 2,064 bytes allocated
==2375==
==2375== All heap blocks were freed -- no leaks are possible
==2375==
==2375== For counts of detected and suppressed errors, rerun with: -v
==2375== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
There is only one alloc and one free at the code. As n = 4, I'd expect it to alloc 4*4(sizeof(int))=16 bytes. Where is this comming from?

Valgrind keeps track of all memory allocations which occur in your application, including ones made internally by the C library. It is not (and cannot) be limited to allocations you make explicitly, as the C library can return pointers to memory which it has allocated internally.
Many standard I/O implementations will allocate buffers for use by printf() and/or scanf(), which is probably what accounts for the numbers you're seeing.

you should only have 1 memory alloc for the 'address' pointer's memory space. the other 2 memory allocs are for the printf and scanf functions.
to proof this, comment out the printf and scanf statements and you should see 1 alloc and 1 free when you use valgrind to execute the program...

Related

Copying a string - how do I have to deal with memory leaks and error cases?

I am trying to implement the function int *cpy_array(int v[], int size), which copies the array in another and returns the new array as pointer. I also have to watch out for error cases and use dynamic memory.
Ok i know that malloc returns 0 when there is nout enough memory available. I was wondering if there might be any other possible errors as well which I missed out. Then I have to implement free() in the case of succsess as well as in error case.
I tried to implement something like:
if (!w[i]) {
for (k = 0; k < i; ++k)
free(w[k]);
return 0;
}
But there was always an error with this.
In file included from hot.c:2:
C:/mingw-w64/i686-8.1.0-posix-dwarf-rt_v6-rev0/mingw32/i686-w64-mingw32/include/stdlib.h:502:27: note: expected 'void *' but argument is of type 'int'"
void __cdecl free(void *_Memory);
And I am not sure why to free() the new array or should the old array be freed? I tried to free it with pointer in my function, but didnt work either and dont think it should be in the main?
Here is the original code:
int *cpy_array(int v[], int size);
int main(void)
{
int size;
size = 4;
int myArray[4] = {1234};
if (*cpy_array(myArray, size) == 0)
{
printf("No memory available.");
}else{
printf("The new Array: %i", *cpy_array(myArray, size));
}
return 0;
}
int *cpy_array(int v[], int size)
{
int i;
int *a = malloc(size * sizeof(int));
if(*a == 0)
return 0;
for (i = 0; i < size; i++)
{
a[i] = v[i];
}
return a;
}
In your first code snippet, you incorrectly deallocated the array of integers w. You can't free single integers in that array, but what you need to do is simply type in:
free(w);
That will free the entire array.
You can also see from the text of the error - note: expected 'void *' but argument is of type 'int'" void __cdecl free(void *_Memory), that the program expected a pointer to the array and not an integer.
You can't free the old array, because it's statically created and the memory for it allocated at the start of the program and it will be freed at the end of the function in which it was defined by the program itself, so you don't need to worry about that. Whereas it's your job to free the dynamically created arrays such as the one you created through the cpy_array(int v[], int size) function.
More on the difference between static and dynamic allocation, you can look up here:
Difference between static memory allocation and dynamic memory allocation
This part of code, wouldn't proparly print the array (you will just print the first number of the array), and also you are calling the function twice, which is excessive and should be done only once for the same array.
if (*cpy_array(myArray, size) == 0)
{
printf("No memory available.");
}else{
printf("The new Array: %i", *cpy_array(myArray, size));
}
You could easify fix these problems by defining a pointer which could store the return value of the function, so you don't have to call it twice and then to correctly print the array use a for loop:
int * copiedArray = cpy_array(myArray, size);
if (copiedArray == NULL)
{
printf("No memory available.");
}else{
printf("The new Array: ");
for (int i = 0; i < size; i++)
printf("%i ", copiedArray[i]);
}
I noticed that you are checking whether a pointer is pointing to something or not incorrectly. Once in main:
if (*cpy_array(myArray, size) == 0)
And once in the cpy_array(int v[], int size) function:
if(*a == 0)
This will not work because you are dereferencing the pointer and checking whether the value to which it is pointing is zero. What you want to do is check the value of the pointer itself. If that is NULL then the allocation didn't work:
if (cpy_array(myArray, size) == NULL)
and
if(a == NULL)
You should use NULL instead of zero because you are explicitly stating that you are checking a value of a pointer, and NULL may not be equal to zero on every machine.
More on that topic here:
What is the difference between NULL, '\0' and 0
To detect you problems concerning the memory use valgrind, If I do that gives :
==10947== Memcheck, a memory error detector
==10947== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==10947== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==10947== Command: ./a.out
==10947==
==10947== Conditional jump or move depends on uninitialised value(s)
==10947== at 0x10548: cpy_array (c.c:25)
==10947== by 0x104B3: main (c.c:11)
==10947==
==10947== Invalid read of size 4
==10947== at 0x104B8: main (c.c:11)
==10947== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==10947==
==10947==
==10947== Process terminating with default action of signal 11 (SIGSEGV)
==10947== Access not within mapped region at address 0x0
==10947== at 0x104B8: main (c.c:11)
==10947== If you believe this happened as a result of a stack
==10947== overflow in your program's main thread (unlikely but
==10947== possible), you can try to increase the size of the
==10947== main thread stack using the --main-stacksize= flag.
==10947== The main thread stack size used in this run was 8388608.
==10947==
==10947== HEAP SUMMARY:
==10947== in use at exit: 16 bytes in 1 blocks
==10947== total heap usage: 1 allocs, 0 frees, 16 bytes allocated
==10947==
==10947== 16 bytes in 1 blocks are definitely lost in loss record 1 of 1
==10947== at 0x4847568: malloc (vg_replace_malloc.c:299)
==10947== by 0x10533: cpy_array (c.c:24)
==10947== by 0x104B3: main (c.c:11)
==10947==
==10947== LEAK SUMMARY:
==10947== definitely lost: 16 bytes in 1 blocks
==10947== indirectly lost: 0 bytes in 0 blocks
==10947== possibly lost: 0 bytes in 0 blocks
==10947== still reachable: 0 bytes in 0 blocks
==10947== suppressed: 0 bytes in 0 blocks
==10947==
==10947== For counts of detected and suppressed errors, rerun with: -v
==10947== Use --track-origins=yes to see where uninitialised values come from
==10947== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 6 from 3)
The "Conditional jump or move depends on uninitialised value(s)" comes from the *a in if(*a == 0) and "Invalid read of size 4 ..." because you dereference 0 because of the return 0;
after changing if(*a == 0) to if(a == 0) to solve the two previous problems that condition is (a priori) false and _valgrind says :
==11116== Memcheck, a memory error detector
==11116== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==11116== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==11116== Command: ./a.out
==11116==
Mein neuer Array enthaelt folgende Zeichen: 1==11116==
==11116== HEAP SUMMARY:
==11116== in use at exit: 32 bytes in 2 blocks
==11116== total heap usage: 3 allocs, 1 frees, 1,056 bytes allocated
==11116==
==11116== 16 bytes in 1 blocks are definitely lost in loss record 1 of 2
==11116== at 0x4847568: malloc (vg_replace_malloc.c:299)
==11116== by 0x10523: cpy_array (c.c:24)
==11116== by 0x104A3: main (c.c:11)
==11116==
==11116== 16 bytes in 1 blocks are definitely lost in loss record 2 of 2
==11116== at 0x4847568: malloc (vg_replace_malloc.c:299)
==11116== by 0x10523: cpy_array (c.c:24)
==11116== by 0x104CF: main (c.c:15)
==11116==
==11116== LEAK SUMMARY:
==11116== definitely lost: 32 bytes in 2 blocks
==11116== indirectly lost: 0 bytes in 0 blocks
==11116== possibly lost: 0 bytes in 0 blocks
==11116== still reachable: 0 bytes in 0 blocks
==11116== suppressed: 0 bytes in 0 blocks
==11116==
==11116== For counts of detected and suppressed errors, rerun with: -v
==11116== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 6 from 3)
so yes you have memory leaks because you lost 2 times the allocation return by cpy_array
you need to have something like :
int * v = cpy_array(myArray, size);
if (*v == 0)
{
printf("Speicher kann nicht freigegeben werden.");
}else{
printf("Mein neuer Array enthaelt folgende Zeichen: %i",
*v);
}
free(v);
Doing that correction valgrind signals nothing :
valgrind --leak-check=full ./a.out
==11224== Memcheck, a memory error detector
==11224== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==11224== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==11224== Command: ./a.out
==11224==
Mein neuer Array enthaelt folgende Zeichen: 1==11224==
==11224== HEAP SUMMARY:
==11224== in use at exit: 0 bytes in 0 blocks
==11224== total heap usage: 2 allocs, 2 frees, 1,040 bytes allocated
==11224==
==11224== All heap blocks were freed -- no leaks are possible
==11224==
==11224== For counts of detected and suppressed errors, rerun with: -v
==11224== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)
I encourage you to
compile with all warning detection, like gcc -g -Wall -pedantic ...
when you have problem use valgrind and/or debugger
even you do not see a problem run anyway under valgrind, so problems can be hidden
this is not the correct way to initialize the array
int myArray[4] = {1234};
write
int myArray[4] = { 1,2,3,4 };
or simply
int myArray[] = { 1,2,3,4 };
Calling the function cpy_array .. when you write
if (*cpy_array(myArray, size) == 0)
Is not correct, why? because what if the function returns NULL, then you are dereferencing NULL
In your function cpy_array you are dereferencing a, that is not correct, instead compare the pointer
if ( a == NULL)
and use the standard constant NULL for a null pointer instead of 0 since it may not be 0 on all platforms.

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.

I don't understand why I get this valgrind error

I got the following code:
/* main.c */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main (){
int i;
char *msg = "This is a simple and small message";
int len = strlen (msg);
char *new_msg = (char *) malloc (len);
for (i = 0; i < len; i++)
new_msg[i] = 'A';
printf ("%s\n", new_msg);
free (new_msg);
return 0;
}
I compiled it and then run it using valgrind with this command:
valgrind --leak-check=full --show-reachable=yes ./main
I got the this output:
==8286== Memcheck, a memory error detector
==8286== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==8286== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==8286== Command: ./main
==8286==
==8286== Invalid read of size 1
==8286== at 0x4C2C1B4: strlen (vg_replace_strmem.c:412)
==8286== by 0x4EA09FB: puts (ioputs.c:36)
==8286== by 0x400636: main (main.c:12)
==8286== Address 0x51de062 is 0 bytes after a block of size 34 alloc'd
==8286== at 0x4C28C20: malloc (vg_replace_malloc.c:296)
==8286== by 0x400601: main (main.c:9)
==8286==
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
==8286==
==8286== HEAP SUMMARY:
==8286== in use at exit: 0 bytes in 0 blocks
==8286== total heap usage: 1 allocs, 1 frees, 34 bytes allocated
==8286==
==8286== All heap blocks were freed -- no leaks are possible
==8286==
==8286== For counts of detected and suppressed errors, rerun with: -v
==8286== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
I see that all the allocated memory was released, but I still get an error that I don't understand.
Appreciate the help.
This is a pretty straightforward error: there is an invalid read of new_msg because the null terminator is not there.
You have allocated the number of chars equal to the length of the original string, so currently there's no space to fit '\0' without making undefined behavior. Change your code as follows to fix the problem:
char *new_msg = malloc (len+1);
for (i = 0; i < len; i++)
new_msg[i] = 'A';
new_msg[len] = '\0';
There are a number of things to be changes in your code.
1) len should be of size_t not int, as strlen() returns of type size_t
2) (char *) malloc (len); drop the cast. This isn't an error, although there are reasons one should not cast.
3) new_msg is not NULL terminated \0. This is the reason the error is occurring.
you use strlen() to get length, but not contain the '\0'.
so when you malloc a new array, you should use len + 1, and set new_msg[len] is '\0'.

malloc doesn't look to work in my program

I have a function which prints the whole content of the file and the function seems to work fine, but valgring complains about Conditional jump or move depends on uninitialised value(s) and Uninitialised value was created by a heap allocation:
==7876== Memcheck, a memory error detector
==7876== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==7876== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==7876== Command: ./program
==7876==
==7876== Conditional jump or move depends on uninitialised value(s)
==7876== at 0x4E864B2: vfprintf (vfprintf.c:1642)
==7876== by 0x4E8CC38: printf (printf.c:33)
==7876== by 0x40074C: main (program.c:45)
==7876== Uninitialised value was created by a heap allocation
==7876== at 0x4C2BBA0: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7876== by 0x4008A7: printFile (program.c:23)
==7876== by 0x40073A: main (program.c:43)
==7876==
The world is not enought and michi is the only one who's not agree.
==7876==
==7876== HEAP SUMMARY:
==7876== in use at exit: 0 bytes in 0 blocks
==7876== total heap usage: 2 allocs, 2 frees, 621 bytes allocated
==7876==
==7876== All heap blocks were freed -- no leaks are possible
==7876==
==7876== For counts of detected and suppressed errors, rerun with: -v
==7876== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Here is the program:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
char *printFile(char *fileName){
size_t length=0,size=0;
char *buffer;
FILE *file;
file = fopen (fileName , "r" );
if (file==NULL){
printf("\n");
printf("\tThe file %s does not Exists\n", fileName);
exit(1);
}
fseek (file , 0 , SEEK_END);
length = (size_t)ftell (file);
fseek (file , 0 , SEEK_SET);
buffer = malloc(length+1);
if (!buffer){
fputs ("Memory error",stderr);
exit (2);
}
size = fread (buffer,1,length+1,file);
if (size != length){
fputs ("Reading error",stderr);
exit(3);
}
fclose (file);
return buffer;
}
int main (void) {
char *fileName = "test.txt";
char *fileContent = printFile(fileName);
printf("%s",fileContent);
free(fileContent);
return 0;
}
A quick fix is to use calloc instead of malloc, because it zeros the returned bytes
So I replaced:
buffer = malloc(length+1);
with:
buffer = calloc(length,sizeof(char*));
And valgrind doesn't complain:
==7897== Memcheck, a memory error detector
==7897== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==7897== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==7897== Command: ./program
==7897==
The world is not enought and michi is the only one who's not agree.
==7897==
==7897== HEAP SUMMARY:
==7897== in use at exit: 0 bytes in 0 blocks
==7897== total heap usage: 2 allocs, 2 frees, 1,096 bytes allocated
==7897==
==7897== All heap blocks were freed -- no leaks are possible
==7897==
==7897== For counts of detected and suppressed errors, rerun with: -v
==7897== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
My question is, why does malloc produce that error and how to avoid calloc.
Do I have some codding problem here or is just malloc?
.
.
EDIT:
if I change:
size = fread (buffer,1,length+1,file);
with:
size = fread (buffer,1,length,file);
I get:
==7985== Memcheck, a memory error detector
==7985== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==7985== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==7985== Command: ./program
==7985==
==7985== Invalid read of size 1
==7985== at 0x4E864B2: vfprintf (vfprintf.c:1642)
==7985== by 0x4E8CC38: printf (printf.c:33)
==7985== by 0x40074C: main (program.c:44)
==7985== Address 0x52022f4 is 0 bytes after a block of size 68 alloc'd
==7985== at 0x4C2BBA0: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7985== by 0x4008A6: printFile (program.c:22)
==7985== by 0x40073A: main (program.c:42)
==7985==
The world is not enought and michi is the only one who's not agree.
==7985==
==7985== HEAP SUMMARY:
==7985== in use at exit: 0 bytes in 0 blocks
==7985== total heap usage: 2 allocs, 2 frees, 620 bytes allocated
==7985==
==7985== All heap blocks were freed -- no leaks are possible
==7985==
==7985== For counts of detected and suppressed errors, rerun with: -v
==7985== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
You print the file content read into your buffer but nothing can ensure that the buffer contains a NUL char, so valgrind complains because printf parse your data until NUL (jump or move depends on uninitialised value(s)). Using calloc tells valgrind that you are more precautious...
Your string must be NUL-terminated. Without it, the program has undefined behaviour, which valgrind rightfully reports.
The easiest way to NUL-terminate the string is:
size = fread (buffer,1,length,file); /* no need to specify useless extra char */
/* it will never be read */
... /* check for errors here */
buffer[length] = '\0'; /* <--- null termination */
calloc fills the entire buffer with NUL characters, but it's a waste of cycles. You only need one.
Memory obtained via malloc() is uninitialized. That's intentional. The workarounds are to use calloc() instead or to initialize that memory obtained via malloc() before you read from it. Under some circumstances you can initialize only part of it, and often you have better initial values available than all zeroes.
Your particular error is only peripherally related to that, however. You do initialize most of the buffer, via fread(), but you allocate one more byte than the file is long, and fread() does not store anything in that last byte. It looks like maybe you intended to add a '\0' terminator, but forgot. It's that last byte that valgrind complains about.
In this case, the memory-clearing performed by calloc() mostly serves no purpose, as you are about to overwrite all bytes in the buffer but one. But it does initialize that last byte, too, which turns out to save you several kinds of trouble when you fail to initialize it any other way.

free 2D array allocated using calloc

I am using a 2D array, and am required to allocate it as shown:
char ** buf; //global var
void allocate()
{
buf = (char **) malloc (10 * sizeof (char*));
char * data = (char *) calloc (1, 1000);
int i;
for(i=0; i<10; i++)
buf[i] = &(data[i*100]);
}
int main()
{
allocate();
//something goes here
free(buf[0]);
free(buf);
return 0;
}
Now to free the arrays, since I cannot access the variable 'data' in main(), I cannot do free(data), hence I do free(buf[0]), assuming that I am freeing the entire array of 1000 elements. Is this the right way to do this? Does free(buf[0]) free the entire 'data' array?
(It would have been convenient to malloc every element of buf as buf[i] = malloc (100), but I cant do that since I HAVE to calloc a big block first).
Thanks in advance.
This code is correct. The value of buf[0] is &(data[0]) which is data by definition. This will free all the allocated memory.
Note that if you really just want one buffer to free, you can set:
offset = 10*sizeof(char*);
buf = calloc(10*100+offset);
and in the loop do:
buf[i] = buf + offset + i*100;
It is slightly unusual, but it is correct. You made two allocations; you make two frees. And you release the pointers that were allocated. All should be clean.
Did you run valgrind on your program?
Valgrind agrees with you. It is correct because buf[0] holds the pointer to the HEAD of the calloc'd memory block.
valgrind ./temp
==15404== Memcheck, a memory error detector
==15404== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==15404== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==15404== Command: ./temp
==15404==
==15404==
==15404== HEAP SUMMARY:
==15404== in use at exit: 0 bytes in 0 blocks
==15404== total heap usage: 2 allocs, 2 frees, 1,040 bytes allocated
==15404==
==15404== All heap blocks were freed -- no leaks are possible
==15404==
==15404== For counts of detected and suppressed errors, rerun with: -v
==15404== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 12 from 7)

Resources