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.
Related
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.
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.
I was reading about the copy elision in c++. And i was having doubts about STL in c++ using this copy elision.
The following code:
#include <vector>
#include <iostream>
using namespace std;
vector<int> merge(vector<int> &arrA, vector<int> &arrB)
{
int x;
vector<int> result;
for(x = 0; x < arrA.size(); x++)
{
result.push_back(arrA[x]);
}
for(x = 0; x < arrB.size(); x++)
{
result.push_back(arrB[x]);
}
cout << "fun return: " << &result <<endl;
return result;
}
int main(int argc, char const *argv[])
{
vector<int> arrA;
arrA.push_back(1);
vector<int> arrB;
arrB.push_back(2);
vector<int> res;
res = merge(arrA, arrB);
cout << "return: " << &res <<endl;
return 0;
}
So I was doing a simple task (merging) the vectors A and B (do not pay attention to the process, just the function and return.
vector<int> merge(vector<int> &arrA, vector<int> &arrB)
With the following definition it is returning a vector<int> (no reference)
And also return result; which is the variable declared in the function scope.
I was trying to see the memory address at which these vectores are located.
output:
==5036== Memcheck, a memory error detector
==5036== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==5036== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==5036== Command: ./a.out
==5036==
fun return: 0xffefffe40
return: 0xffefffe20
==5036==
==5036== HEAP SUMMARY:
==5036== in use at exit: 0 bytes in 0 blocks
==5036== total heap usage: 5 allocs, 5 frees, 28 bytes allocated
==5036==
==5036== All heap blocks were freed -- no leaks are possible
==5036==
==5036== For counts of detected and suppressed errors, rerun with: -v
==5036== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
The memory address is different for both so I was thinking that as long as it will no make a copy-construtor, it will be the same memory address at the end (0xffefffe40) Does that means it is copy-constructed?
Is this method being copy elision?
if not: why it is not copy elision?
if yes: How can I know it is really doing the copy elision?
And the important one: if this is not being copy elision, is it possible to do it? what is needed in order to do the copy elision in STL?
For copy elision, you need to have the "copy" in the first place, i.e. your res vector has to be copy constructed from the return value.
Otherwise you'll just have an assignment, which requires getting rid of whatever was in the vector and as such cannot be elided.
Notice that it would still be a move assignment, so the drawback won't be that much (You can test it with memcheck too).
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?
Consider the following C++ program:
#include <cstdlib> // for exit(3)
#include <string>
#include <iostream>
using namespace std;
void die()
{
exit(0);
}
int main()
{
string s("Hello, World!");
cout << s << endl;
die();
}
Running this through valgrind shows this (some output trimmed for brevity):
==1643== HEAP SUMMARY:
==1643== in use at exit: 26 bytes in 1 blocks
==1643== total heap usage: 1 allocs, 0 frees, 26 bytes allocated
==1643==
==1643== LEAK SUMMARY:
==1643== definitely lost: 0 bytes in 0 blocks
==1643== indirectly lost: 0 bytes in 0 blocks
==1643== possibly lost: 26 bytes in 1 blocks
==1643== still reachable: 0 bytes in 0 blocks
==1643== suppressed: 0 bytes in 0 blocks
As you can see, there's a possibility that 26 bytes allocated on the heap were lost. I know that the std::string class has a 12-byte struct (at least on my 32-bit x86 arch and GNU compiler 4.2.4), and "Hello, World!" with a null terminator has 14 bytes. If I understand it correctly, the 12-byte structure contains a pointer to the character string, the allocated size, and the reference count (someone correct me if I'm wrong here).
Now my questions: How are C++ strings stored with regard to the stack/heap? Does a stack object exist for a std::string (or other STL containers) when declared?
P.S. I've read somewhere that valgrind may report a false positive of a memory leak in some C++ programs that use STL containers (and "almost-containers" such as std::string). I'm not too worried about this leak, but it does pique my curiosity regarding STL containers and memory management.
Calling exit "terminates the program without leaving the current block and hence without
destroying any objects with automatic storage duration".
In other words, leak or not, you shouldn't really care. When you call exit, you're saying "close this program, I no longer care about anything in it." So stop caring. :)
Obviously it's going to leak resources because you never let the destructor of the string run, absolutely regardless of how it manages those resources.
Others are correct, you are leaking because you are calling exit. To be clear, the leak isn't the string allocated on the stack, it is memory allocated on the heap by the string. For example:
struct Foo { };
int main()
{
Foo f;
die();
}
will not cause valgrind to report a leak.
The leak is probable (instead of definite) because you have an interior pointer to memory allocated on the heap. basic_string is responsible for this. From the header on my machine:
* A string looks like this:
*
* #code
* [_Rep]
* _M_length
* [basic_string<char_type>] _M_capacity
* _M_dataplus _M_refcount
* _M_p ----------------> unnamed array of char_type
* #endcode
*
* Where the _M_p points to the first character in the string, and
* you cast it to a pointer-to-_Rep and subtract 1 to get a
* pointer to the header.
They key is that _M_p doesn't point to the start of the memory allocated on the heap, it points to the first character in the string. Here is a simple example:
struct Foo
{
Foo()
{
// Allocate 4 ints.
m_data = new int[4];
// Move the pointer.
++m_data;
// Null the pointer
//m_data = 0;
}
~Foo()
{
// Put the pointer back, then delete it.
--m_data;
delete [] m_data;
}
int* m_data;
};
int main()
{
Foo f;
die();
}
This will report a probable leak in valgrind. If you comment out the lines where I move m_data valgrind will report 'still reachable'. If you uncomment the line where I set m_data to 0 you'll get a definite leak.
The valgrind documentation has more information on probable leaks and interior pointers.
Of course this "leaks", by exiting before s's stack frame is left you don't give s's destructor a chance to execute.
As for your question wrt std::string storage: Different implementations do different things. Some allocate some 12 bytes on the stack which is used if the string is 12 bytes or shorter. Longer strings go to the heap. Other implementations always go to the heap. Some are reference counted and with copy-on-write semantics, some not. Please turn to Scott Meyers' Effective STL, Item 15.
gcc STL has private memory pool for containers and strings. You can turn this off ; look in valgrind FAQ
http://valgrind.org/docs/manual/faq.html#faq.reports
I would avoid using exit() I see no real reason to use that call. Not sure if it will cause the process to stop instantly without cleaning up the memory first although valgrind does still appear to run.