Why does memory leak in one case and not in another - c++

I am creating a c++ object with two slightly different ways, in the following code when CASE is 0 there is a memory leak, but no memory leak in the else case.
#include <string>
#define CASE 1
class A {
private:
std::string *s;
public:
A(std::string *p_s) { s = p_s; }
};
int main() {
#if CASE==0
auto a = A(new std::string("Hello"));
#else
auto s = std::string("Hello");
auto a = A(&s);
#endif
}
when I set CASE 0 the valgrind says that there is a memory leak
valgrind ./a.out
==24351== Memcheck, a memory error detector
==24351== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==24351== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==24351== Command: ./a.out
==24351==
==24351==
==24351== HEAP SUMMARY:
==24351== in use at exit: 32 bytes in 1 blocks
==24351== total heap usage: 2 allocs, 1 frees, 72,736 bytes allocated
==24351==
==24351== LEAK SUMMARY:
==24351== definitely lost: 32 bytes in 1 blocks
==24351== indirectly lost: 0 bytes in 0 blocks
==24351== possibly lost: 0 bytes in 0 blocks
==24351== still reachable: 0 bytes in 0 blocks
==24351== suppressed: 0 bytes in 0 blocks
==24351== Rerun with --leak-check=full to see details of leaked memory
==24351==
==24351== For counts of detected and suppressed errors, rerun with: -v
==24351== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
in the else case (i.e. define CASE 1) it works as expected and valgrind doesn't report any memory leak.
I am not able to understand in either case I am passing a pointer and I am not explicitly freeing the memory then why do they behave differently?

The reason for this behavior is that your class A is not designed to take ownership of std::string* passed into it: its std::string *s member assumes that the object the pointer to which is passed into the constructor would be destroyed externally.
This leads to a memory leak when the object is not destroyed: delete is never called on new string passed into the constructor in the first case, causing a memory leak.
In the second case the pointer points to a string in automatic storage. It gets destroyed when main ends, preventing the memory leak.

You don't get a memory leak because you have a pointer.
You get a memory leak because you new'd something and did not delete it.
Obtaining a pointer to an automatic storage variable does not stop the variable from being cleaned up automatically.
In fact, attempting to delete &a in that case would be wrong/broken/evil/illegal/heresy.

CASE==0
auto a = A(new std::string("Hello"));
This means you are new-ing an object in heap -> you have to explicitly delete it - that you didn't in the snippet -> memory leaks.
else
auto s = std::string("Hello");
auto a = A(&s);
auto s = std::string("Hello");: This means you are creating an object in stack and,
auto a = A(&s);: take its address (in stack, of course).
The created object will be auto-deleted once the variable goes out of scope
-> no memory leak.

This is no different from:
// first case, leak
int *j = new int (5);
//
// second case, no leak
int q = 5;
int *j = &q;
In the first case, we've allocated memory with new and it's our responsibility to delete it when we're done. In the second case, we create q on the stack and it's destroyed when it goes out of scope.

Related

memory leaked when globaly declared?

Is this code still going to leak if instead of declaring the pointers as part of main I declare them globally?
I tested with Valgrind memcheck and it doesn't
class Test1 {
public:
Test1() { std::cout << "Constructor of Test " << std::endl; }
~Test1() { std::cout << "Destructor of Test " << std::endl; }
};
//Memory leaked or not when globally declared?
// Test1 *t1;
// Test1 *t2;
// Test1 *t;
int main()
{
//mem will leak if not deallocated later
Test1 *t1;
Test1 *t2;
Test1 *t;
try {
t1=new Test1[100];
t2=new Test1;
t =new Test1;
throw 10;
}
catch(int i)
{
std::cout << "Caught " << i << std::endl;
// delete []t1;
// delete t;
// delete t2;
}
return 0;
}
Declaring the variable global will make the pointer variable global, not what the pointer points to (which is already global as it is located on the heap).
Therefore, your current implementation also has a leak.
Local variables get destroyed when out of scope, but what they point to is not automatically out. Suggestion: forget completety new and delete operators and use STL or smart pointers.
Edit: You are asking why valgrind does not detect it, this is a different question than the original (I edited to add a tag).
Right now you're always leaking memory, regardless if you're declaring pointers in main or globally.
Whenever you use new in your code, you need to use a delete or delete[].
In modern C++, using new is considered a bad practice, you should be using std::vector, if you want an array, or std::unique_ptr if you're managing a pointer to an object.
As was mentioned already in other answers, the allocated object's destructor will not be called in both variants of your program, the scope and lifetime of the pointers do not influence what happens to the pointees, but you showed that already by printing in the destructor.
Valgrind will report this slightly differently however.
I ran the with a shorter array of 2 elements to reduce the amount of output.
The heap summary, which tells you what data remains on the heap at the end of the run, is the same for both programs:
==397== HEAP SUMMARY:
==397== in use at exit: 12 bytes in 3 blocks
==397== total heap usage: 6 allocs, 3 frees, 76,944 bytes allocated
That means both programs never deallocated the objects.
Valgrind does however make a difference between "definitely lost" allocations, with no reference to the memory blocks remaining in any variable and "still reachable" allocations, where a reference remains.
The leak summary with local pointers
==397== LEAK SUMMARY:
==397== definitely lost: 12 bytes in 3 blocks
==397== indirectly lost: 0 bytes in 0 blocks
==397== possibly lost: 0 bytes in 0 blocks
==397== still reachable: 0 bytes in 0 blocks
==397== suppressed: 0 bytes in 0 blocks
The leak summary with global pointers
==385== LEAK SUMMARY:
==385== definitely lost: 0 bytes in 0 blocks
==385== indirectly lost: 0 bytes in 0 blocks
==385== possibly lost: 0 bytes in 0 blocks
==385== still reachable: 12 bytes in 3 blocks
==385== of which reachable via heuristic:
==385== length64 : 10 bytes in 1 blocks
If the pointers are local, valgrind can be sure that no reference remains, because after main returns, the stack locations are no longer valid.
If the pointers are global, they remain valid and could thus still be used or deallocated.
Why does valgrind make this distinction?
Especially in historic C programs it may be considered legitimate to allocate some memory once and use it throughout the execution, without bothering to later free the memory. The operating system will clean up the whole virtual memory space of the program anyway once the program exits. So while this could be a bug, it could also be intentional.
If you are interested in such leaks, valgrind itself tells you how it must be called to see them:
==405== Reachable blocks (those to which a pointer was found) are not shown.
==405== To see them, rerun with: --leak-check=full --show-leak-kinds=all
"Definitely lost" memory is always suspicious, however, and that is why valgrind distinguished the cases. The value of a tool like valgrind lies in its precision. It is not sufficient to report many actual errors, in order to be useful it must also strive to produce a low number of false positives, otherwise looking at the reports would too often be a waste of developer time.
In modern C++, there are not many excuses for leaking memory, as std::unique_ptr should be the way to allocate dynamic objects. std::vector should be used for dynamic arrays and local objects used wherever possible as the compiler never forgets a deallocation. Even for singletons, the noise in the output of tools like valgrind and address sanitizer usually outweighs the usually minuscule benefits of saving one destructor call or deallocation.

C++ returning a pointer coming out of another function is copying it ? valgrind complains

sorry to post this, but i have not found any discussion dealing with the feeling i have when reading valgrind results. What i see is part of a large code, so i've tried to simplify it as much as possible.I have a class (ClassA), that contains a pointer to a object of another class (ClassB). Both classes have a method named getArr that returns a double*. The one in ClassA basically returns a call to the one from ClassB through its pointer.
from what valgrind tells me, i've the feeling that ClassA is not really returning the pointer from its ClassB object but that it might copy it... Is is correct and if so how to avoid it ?
here is the header:
class ClassB
{
public:
ClassB(){}
~ClassB(){}
double *getArr();
};
class ClassA
{
public:
ClassA();
~ClassA();
double *getArr();
ClassB *myB;
};
the functions:
#include <iostream>
#include "OtherClasses.h"
using namespace std;
ClassA::ClassA()
{
myB = new ClassB();
}
ClassA::~ClassA()
{
if( myB )
delete myB;
}
double* ClassA::getArr()
{
return (myB->getArr());
}
double* ClassB::getArr()
{
double* arr = new double[10];
for(unsigned int i=0; i<10; i++)
arr[i]=i;
return arr;
}
int main(int argc, char *argv[])
{
ClassA *myA = new ClassA();
double* pouet = myA->getArr();
for(unsigned int i=0; i<10; i++)
cout<<pouet[i]<<endl;
delete[] pouet;
if (myA)
delete myA;
}
and what is displayed:
==2115== Memcheck, a memory error detector
==2115== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==2115== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==2115== Command: ./bin/main
==2115==
0
1
2
3
4
5
6
7
8
9
==2115==
==2115== HEAP SUMMARY:
==2115== in use at exit: 72,704 bytes in 1 blocks
==2115== total heap usage: 4 allocs, 3 frees, 72,793 bytes allocated
==2115==
==2115== 72,704 bytes in 1 blocks are still reachable in loss record 1 of 1
==2115== at 0x4A06C0F: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==2115== by 0x350388A1EF: ??? (in /usr/lib64/libstdc++.so.6.0.21)
==2115== by 0x34FD80F669: call_init.part.0 (in /usr/lib64/ld-2.21.so)
==2115== by 0x34FD80F77A: _dl_init (in /usr/lib64/ld-2.21.so)
==2115== by 0x34FD800CC9: ??? (in /usr/lib64/ld-2.21.so)
==2115==
==2115== LEAK SUMMARY:
==2115== definitely lost: 0 bytes in 0 blocks
==2115== indirectly lost: 0 bytes in 0 blocks
==2115== possibly lost: 0 bytes in 0 blocks
==2115== still reachable: 72,704 bytes in 1 blocks
==2115== suppressed: 0 bytes in 0 blocks
==2115==
==2115== For counts of detected and suppressed errors, rerun with: -v
==2115== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
thanks in advance
jbb
EDIT: As said in the comments the behaviour described above is consistent with valgrind 3.10 and 3.11 and using g++ 5.1, 5.3 and clang++... The only compilator that gives 3 alloc and 3 frees (so no problem at all) is g++ 4.8
#Sarthak Singh: Removing the delete myB in ClassA destructor brings these line in the output of valgrind
==23329== 1 bytes in 1 blocks are definitely lost in loss record 1 of 2
==23329== at 0x4A07117: operator new(unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==23329== by 0x400A4C: ClassA::ClassA() (main.cpp:8)
==23329== by 0x400B2E: main (main.cpp:34)
it seems to me the leak is coming from libstdc++:
$> valgrind --leak-check=full --show-leak-kinds=all ./a.out
[...]
==6664== 72,704 bytes in 1 blocks are still reachable in loss record 1 of 1
==6664== at 0x4C2ABD0: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6664== by 0x4EBFE7F: pool (eh_alloc.cc:117)
==6664== by 0x4EBFE7F: __static_initialization_and_destruction_0 (eh_alloc.cc:244)
==6664== by 0x4EBFE7F: _GLOBAL__sub_I_eh_alloc.cc (eh_alloc.cc:307)
==6664== by 0x400F3B9: call_init.part.0 (in /usr/lib/ld-2.23.so)
==6664== by 0x400F4CA: _dl_init (in /usr/lib/ld-2.23.so)
==6664== by 0x4000DC9: ??? (in /usr/lib/ld-2.23.so)
[...]
(which explains why the leak is only seen when using gcc-5.x)
it's either a real leak or some interplay b/w the libstdc++ version shipped with gcc-5.x and the hooks valgrind injects into the monitored process.
AFAIK, nothing much you can do about it.
Try removing the destructor of ClassB as delete just calls the destructor if it is defined.
You could read this for more info Delete calling destructor but not deleting object?

C++ destructor and memory allocation, and undefined beahviour

Firstly: I know that if the destructor of an object throws the behavior of the application cannot be counted on... The question is about memory issues.
So, now that this is clear:
See the app:
#include <stdlib.h>
#include <iostream>
class T
{
public:
T() : ma(0)
{std::cout << "T::T ->default<-" << std::endl; }
T(const char* a) : ma(a)
{std::cout << "T::T ->" << ma << "<-" << std::endl; }
~T()
{std::cout << "T::~T ->" << ma << "<-" << std::endl; }
private:
const char* ma;
};
int main()
{
T* t = new T();
delete t;
}
and see it's valgrind output:
$ valgrind ./a.out
==29554== Memcheck, a memory error detector
==29554== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==29554== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==29554== Command: ./a.out
==29554==
T::T ->default<-
T::~T ->==29554==
==29554== HEAP SUMMARY:
==29554== in use at exit: 0 bytes in 0 blocks
==29554== total heap usage: 1 allocs, 1 frees, 4 bytes allocated
==29554==
==29554== All heap blocks were freed -- no leaks are possible
==29554==
==29554== For counts of detected and suppressed errors, rerun with: -v
==29554== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Explanation: T::~T ->==29554== tells me the destructor has encountered a dangerous sitation (std::cout took in a null value which is undefined) so the behaviour of the application is uncontrollable...
Since it does not print out the "<-" and it gives me the valgrind prompt immediately I expect it exited at that specific point. Valgrind does not report any segfault or something like that ...
But also, valgrind reports no memory leaks... and this is confusing me ... so what I think that happens is:
I call delete t;
the application frees the memory of t
the destructor of t is called.
Can you please explain what is happening here?
Edit: To have a more clear question:
Is the destructor called on the freed memory or there is no undefined behaviour in the destructor when std::cout gets a null object?
Undefined behaviour is undefined.
If I had to guess, it looks like, in this case, the stream detects the null pointer and goes into an error state, so you simply don't see any more output. The rest of the delete process apparently continues as expected.
Other forms of undefined behaviour, for example actually dereferencing a null pointer, might give different results. Likewise, other stream implementations may behave differently when you break their requirements.
Valgrind is right, there is no memory leak.
You allocated in the heap the Variable t but not the inner workings of the Class T. So the destructor has nothing to deallocate since you took the responsibility of deallocating the memory using delete.
You could allocate a variable inside Class T and not deallocating it in the destructor to see a memory leak.

Valgrind legitimate "possibly lost" bytes example

I saw that valgrind classifies memory leaks into:
definitely lost
indirectly lost
possibly lost
still reachable
suppressed
I just fixed a leak where the "possibly lost" was the main problem.
The documentation says: "possibly lost means your program is leaking memory, unless you're doing unusual things with pointers that could cause them to point into the middle of an allocated block; see the user manual for some possible causes"
May I please know an example of "doing unusual things with pointers that could cause them to point into the middle of an allocated block" ?
I mean an example where "possibly lost" can be ignored although it is reported by valgrind. An example in which the use of pointers makes valgrind complain but at the same time the use of the pointers in that way is somehow legitimate
Thank you
Some examples of what the documentation are different libraries that have their own allocators and for which the memory returned is not directly the pointer returned by the underlying OS allocator (malloc/sbrk), but a pointer after an offset. Consider for example, an allocator that obtained some extra memory and stored meta information (maybe type information for a garbage collector...). The process of allocation and deallocation would be similar to:
void* allocate( size_t size ) {
metainfo_t *m = (metainfo_t*) malloc( size + sizeof(metainfo) );
m->data = some_value;
return (void*)(m+1); // [1]
}
void deallocate( void* p ) {
metainfo_t *m = ((metainfo_t*)p) - 1;
// use data
}
void * memory = allocate(10);
When valgrind is tracking the memory, it remembers the original pointer that was returned by malloc, and that pointer is not stored anywhere in the program. But that does not mean that the memory has been leaked, it only means that the pointer is not directly available in the program. In particular memory still holds the returned pointer, and deallocate can be called to release it, but valgrind does not see the original returned pointer at location (char*)memory - sizeof(metadata_t) anywhere in the program and warns.
char *p = malloc(100);
if (p != 0)
{
p += 50;
/* at this point, no pointer points to the start of the allocated memory */
/* however, it is still accessible */
for (int i = -50; i != 50; i++)
p[i] = 1;
free (p - 50);
}
char *p = malloc(100);
if (p != 0)
{
p += 50;
/* at this point, no pointer points to the start of the allocated memory */
/* however, it is still accessible */
for (int i = -50; i != 50; i++)
p[i] = 1;
free (p - 50);
}
Since it looks very interesting, I did run the code and valgrind it. The result is the following.
yjaeyong#carbon:~$ valgrind test
==14735== Memcheck, a memory error detector
==14735== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==14735== Using Valgrind-3.6.1-Debian and LibVEX; rerun with -h for copyright info
==14735== Command: test
==14735==
==14735==
==14735== HEAP SUMMARY:
==14735== in use at exit: 0 bytes in 0 blocks
==14735== total heap usage: 32 allocs, 32 frees, 2,017 bytes allocated
==14735==
==14735== All heap blocks were freed -- no leaks are possible
==14735==
==14735== For counts of detected and suppressed errors, rerun with: -v
==14735== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 11 from 6)
It says no leaks are possible. Am I missing anything?

vector pointer causing valgrind memory leak

I'm trying to learn C++ and valgrind. So I wrote the following code to test it out. But I get some memory leaks. Can anyone explain what's causing the memory leak? Thanks in advance.
#include <vector>
#include <iostream>
using namespace std;
class test
{
int c;
public:
void whatever();
};
void test:: whatever()
{
vector<test*> a;
if(true)
{
test* b = new test();
b->c = 1;
a.push_back(b);
}
test* d = a.back();
cout << "prints: " << d->c;
delete d;
}
int main()
{
test* a = new test();
a->whatever();
return 1;
}
from valgrind
==28548== HEAP SUMMARY:
==28548== in use at exit: 4 bytes in 1 blocks
==28548== total heap usage: 3 allocs, 2 frees, 16 bytes allocated
==28548==
==28548== 4 bytes in 1 blocks are definitely lost in loss record 1 of 1
==28548== at 0x4C27CC1: operator new(unsigned long) (vg_replace_malloc.c:261)
==28548== by 0x400C36: main (in a.out)
==28548==
==28548== LEAK SUMMARY:
==28548== definitely lost: 4 bytes in 1 blocks
==28548== indirectly lost: 0 bytes in 0 blocks
==28548== possibly lost: 0 bytes in 0 blocks
==28548== still reachable: 0 bytes in 0 blocks
==28548== suppressed: 0 bytes in 0 blocks
==28548==
==28548== For counts of detected and suppressed errors, rerun with: -v
==28548== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4)
Am I not allowed to delete from a copy of a pointer or am I doing something else wrong?
You never call delete on a.
Of course, the important bit here is that you are using a vector of pointers. Why in the world would you do this? Let the vector take care of memory management for you!
You forgot to delete a; at the end of main().
Note that everything you wrote should never go into real code. You should never use dynamic allocation (new) unless you absolutely have to and know precisely why.
Assuming you want to maintain the vector of pointers for educational purposes, then here's a better way of writing it:
#include <vector>
#include <memory> // for unique_ptr
// intentionally left blank; NO abusing namespace std!
struct Foo
{
int c;
void whatever()
{
std::vector<std::unique_ptr<test>> v;
if (true)
{
v.emplace_back(new test);
v.back()->c = 1;
}
// everything is cleaned up automagically
}
};
int main()
{
Test a; // automatic, not dynamic
a.whatever();
return 1;
}
This is still just for educational purposes; in real life you would try very hard to make do with a plain std::vector<test>, since vector is already a dynamic data structure and there is little need for the extra level of indirection.
The memory leak is in main. You are not deleting the allocated test object.