I meet a problem when I am testing C++.
When i am running the first code no error it throws while the second code throws "double free error". Anyone knows what is going on?
Test* test1 = new Test(1);
Test* test2 = new Test(2);
delete test1;
delete test2;
delete test1;
delete test2;
Test* test1 = new Test(1);
Test* test2 = new Test(2);
delete test1;
delete test1;
delete test2;
delete test2;
To better understand heap usage of a program you can use valgrind on Gnu/Linux. When I run your program under valgrind I get this. Please see the summary line
total heap usage: 2 allocs, 4 frees, 8 bytes allocated
valgrind ./a.out
==7594== Memcheck, a memory error detector
==7594== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==7594== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
==7594== Command: ./a.out
==7594==
==7594== Invalid free() / delete / delete[] / realloc()
==7594== at 0x4C2A360: operator delete(void*) (vg_replace_malloc.c:507)
==7594== by 0x40069E: main (in /home/ppm/algo/src/stackoverflow/a.out)
==7594== Address 0x5a02040 is 0 bytes inside a block of size 4 free'd
==7594== at 0x4C2A360: operator delete(void*) (vg_replace_malloc.c:507)
==7594== by 0x400686: main (in /home/ppm/algo/src/stackoverflow/a.out)
==7594==
==7594== Invalid free() / delete / delete[] / realloc()
==7594== at 0x4C2A360: operator delete(void*) (vg_replace_malloc.c:507)
==7594== by 0x4006AA: main (in /home/ppm/algo/src/stackoverflow/a.out)
==7594== Address 0x5a02090 is 0 bytes inside a block of size 4 free'd
==7594== at 0x4C2A360: operator delete(void*) (vg_replace_malloc.c:507)
==7594== by 0x400692: main (in /home/ppm/algo/src/stackoverflow/a.out)
==7594==
==7594==
==7594== HEAP SUMMARY:
==7594== in use at exit: 0 bytes in 0 blocks
==7594== total heap usage: 2 allocs, 4 frees, 8 bytes allocated
==7594==
==7594== All heap blocks were freed -- no leaks are possible
==7594==
==7594== For counts of detected and suppressed errors, rerun with: -v
==7594== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
Related
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 wrote a small piece of code like this:
template <class T>
void
test()
{
T* ptr = nullptr;
ptr = (T*)malloc(1 * sizeof(T));
new ((void*)ptr) T(T());
ptr = (T*)realloc(ptr, 2 * sizeof(T));
new ((void*)(ptr + 1)) T(T());
(ptr)->~T();
(ptr + 1)->~T();
free(ptr);
}
struct foo
{
foo() : ptr(malloc(10)) {}
~foo() { free(ptr); }
void* ptr;
};
int
main()
{
test<int>(); // this is ok
test<foo>(); // this is ok
test<std::string>(); // memory error :(
return 0;
};
When T is [int] or [foo], everything works fine. But using [std::string] as T causes valgrind to report memory errors like this:
==18184== Memcheck, a memory error detector
==18184== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==18184== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==18184== Command: ./a.out
==18184==
==18184== Invalid free() / delete / delete[] / realloc()
==18184== at 0x4C2C20A: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==18184== by 0x401074: void test<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >() (tmp.cpp:26)
==18184== by 0x400CFC: main (tmp.cpp:44)
==18184== Address 0x5a89e70 is 16 bytes inside a block of size 32 free'd
==18184== at 0x4C2CC37: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==18184== by 0x401042: void test<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >() (tmp.cpp:22)
==18184== by 0x400CFC: main (tmp.cpp:44)
==18184== Block was alloc'd at
==18184== at 0x4C2AB8D: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==18184== by 0x40100F: void test<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >() (tmp.cpp:18)
==18184== by 0x400CFC: main (tmp.cpp:44)
==18184==
==18184==
==18184== HEAP SUMMARY:
==18184== in use at exit: 0 bytes in 0 blocks
==18184== total heap usage: 9 allocs, 10 frees, 72,856 bytes allocated
==18184==
==18184== All heap blocks were freed -- no leaks are possible
==18184==
==18184== For counts of detected and suppressed errors, rerun with: -v
==18184== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
why only [std::string] leads to memory problem while [foo] also has malloc/free in both ctor & dtor ?
I'm using g++ 6.2.1 and valgrind 3.12.0
malloc(), free(), and realloc() are C library functions, that know absolutely nothing about C++ classes, their constructors, and destructors.
You are using malloc() with placement new to construct a std::string using malloc-ed memory. This is fine.
But then, you're using realloc() to reallocate the allocated memory.
Copying/moving C++ objects in memory must be done using the respective objects' copy/move constructors. Copying/moving C++ objects in memory cannot be done with realloc().
The only way to do this is to malloc() a new memory block, use placement new to invoke the objects' copy/move constructors in order to copy/move them into the new memory block, and finally invoke the destructor of the objects in the old memory block, after which it can be free()-ed.
realloc is not compatible with non-POD types.
Because it can move things in memory without the moved objects being aware of it.
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?
I found this memory leak from Valgrind which gave the memory error: Invalid free() / delete / delete[] / realloc().
==7367== Invalid free() / delete / delete[] / realloc()
==7367== at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7367== by 0x40077F: ItemSet::~ItemSet() (cart.cpp:33)
==7367== by 0x40086B: ShoppingCart::~ShoppingCart() (cart.cpp:14)
==7367== by 0x400828: main (cart.cpp:45)
==7367== Address 0x5a1c0b0 is 0 bytes inside a block of size 40 free'd
==7367== at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7367== by 0x40077F: ItemSet::~ItemSet() (cart.cpp:33)
==7367== by 0x400800: ShoppingCart::ShoppingCart() (cart.cpp:39)
==7367== by 0x400817: main (cart.cpp:43)
==7367==
==7367==
==7367== HEAP SUMMARY:
==7367== in use at exit: 40 bytes in 1 blocks
==7367== total heap usage: 2 allocs, 2 frees, 80 bytes allocated
==7367==
==7367== LEAK SUMMARY:
==7367== definitely lost: 40 bytes in 1 blocks
==7367== indirectly lost: 0 bytes in 0 blocks
==7367== possibly lost: 0 bytes in 0 blocks
==7367== still reachable: 0 bytes in 0 blocks
==7367== suppressed: 0 bytes in 0 blocks
==7367== Rerun with --leak-check=full to see details of leaked memory
==7367==
==7367== For counts of detected and suppressed errors, rerun with: -v
==7367== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Here is the code. Its a simplified version of my program, but it still has the problem I am having.
#include <cstdlib>
class ItemSet {
private:
int* items;
public:
ItemSet();
virtual ~ItemSet();
// ItemSet Methods...
};
class ShoppingCart {
private:
ItemSet items_in_cart;
public:
ShoppingCart();
// ShoppingCart methods...
};
ItemSet::ItemSet() {
// Constructor
int max_num_of_items = 10;
items = (int*)calloc(sizeof(int), max_num_of_items);
}
ItemSet::~ItemSet() {
// Destructor
if (NULL != items) {
// Frees the dynamically allocated register files
free(items);
}
}
ShoppingCart::ShoppingCart() {
// Constructor
items_in_cart = ItemSet();
}
int main() {
ShoppingCart cart = ShoppingCart();
return 0;
}
ShoppingCart::ShoppingCart() {
// Constructor
items_in_cart = ItemSet();
}
That last line can't possibly work. Right after the assignment, we have two ItemSet objects with the same value for items -- the temporary created on the right side and items_in_cart. When the second one is destroyed, you have a double free.
Use a sensible method of having a collection of objects like std::list, std::vector, or std::array. Otherwise, follow the rule of 3, rule of 5, or of zero.
See the program below:
#include <cstdio>
#include <cstring>
#include <iostream>
class Chaine {
private:
char* _donnees;
unsigned int _taille;
public:
Chaine();
Chaine(const char*);
~Chaine();
unsigned int taille() const;
};
Chaine::Chaine():_taille(0) {
_donnees=new char[1];
_donnees[0]='\0';
}
Chaine::Chaine(const char *s) {
_taille = std::strlen(s);
_donnees = new char[_taille + 1];
std::strcpy(_donnees, s);
std::printf("%s(%d): %s\n", __FILE__, __LINE__, __func__);
}
Chaine::~Chaine() {
if(*_donnees == 0){
std::printf("_donnees points to freed block\n");
}
else{
std::printf("_donnees points to freed block\n");
delete[] _donnees;
_donnees=NULL;
}
std::printf("%s(%d): %s\n", __FILE__, __LINE__, __func__);
}
unsigned int Chaine::taille() const{
return _taille;
}
int main() {
Chaine s1("une chaine");
Chaine *s2 = new Chaine("s3");
Chaine s3 = s1;
delete s2;
}
I compiled using g++ -Wall -o test test.cpp then run valgrind --leak-check=full ./test and got messages below:
/test
==5638== Memcheck, a memory error detector
==5638== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==5638== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==5638== Command: ./test
==5638==
test.cpp(29): Chaine
test.cpp(29): Chaine
_donnees points to freed block
test.cpp(41): ~Chaine
_donnees points to freed block
test.cpp(41): ~Chaine
==5638== Invalid read of size 1
==5638== at 0x804886D: Chaine::~Chaine() (in /home/qliang/Documents/ENSEIRB/cpp/td2/chaine2/test)
==5638== by 0x804895F: main (in /home/qliang/Documents/ENSEIRB/cpp/td2/chaine2/test)
==5638== Address 0x4353028 is 0 bytes inside a block of size 11 free'd
==5638== at 0x402B598: operator delete[](void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==5638== by 0x80488A3: Chaine::~Chaine() (in /home/qliang/Documents/ENSEIRB/cpp/td2/chaine2/test)
==5638== by 0x8048953: main (in /home/qliang/Documents/ENSEIRB/cpp/td2/chaine2/test)
==5638==
_donnees points to freed block
==5638== Invalid free() / delete / delete[] / realloc()
==5638== at 0x402B598: operator delete[](void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==5638== by 0x80488A3: Chaine::~Chaine() (in /home/qliang/Documents/ENSEIRB/cpp/td2/chaine2/test)
==5638== by 0x804895F: main (in /home/qliang/Documents/ENSEIRB/cpp/td2/chaine2/test)
==5638== Address 0x4353028 is 0 bytes inside a block of size 11 free'd
==5638== at 0x402B598: operator delete[](void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==5638== by 0x80488A3: Chaine::~Chaine() (in /home/qliang/Documents/ENSEIRB/cpp/td2/chaine2/test)
==5638== by 0x8048953: main (in /home/qliang/Documents/ENSEIRB/cpp/td2/chaine2/test)
==5638==
test.cpp(41): ~Chaine
==5638==
==5638== HEAP SUMMARY:
==5638== in use at exit: 0 bytes in 0 blocks
==5638== total heap usage: 3 allocs, 4 frees, 22 bytes allocated
==5638==
==5638== All heap blocks were freed -- no leaks are possible
==5638==
==5638== For counts of detected and suppressed errors, rerun with: -v
==5638== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
I the deconstructor, I want to check if the memory _donnees points to has been freed to avoid re-free.
One solution(maybe bad solution) is to declare a static integer in deconstructor, like
Chaine::~Chaine() {
static int num_free = 0;
if(num_free == 1){
std::printf("_donnees points to freed block\n");
}
else{
std::printf("_donnees points to freed block\n");
delete[] _donnees;
num_free = 1;
_donnees=NULL;
}
std::printf("%s(%d): %s\n", __FILE__, __LINE__, __func__);
}
But I want to know if there is some way like *_donnees == NULL to check if the block of memory is freed or not.
And, why valgrind displays messages:
==5638== Invalid read of size 1
==5638== Invalid free() / delete / delete[] / realloc()
and why each of these messages just show once?
You are violating the Rule of Three. You should define a copy constructor and a copy assignment operator.