Reputation: 691
I'm developing a C++ application and there I need to copy the contents of a std::set to a std::deque. Something similar to what I'm doing in my application is as follows. ( This is a simplified version)
class A
{
public:
A(){};
~A() {};
void UpdateDataSet(std::set<C>& _setData);
private:
std::deque<C> deque_Data;//contains ohlc data for the symbol
};
void A::UpdateDataSet(std::set<C>& _setData)
{
std::set<C>::iterator itrSet = _setData.begin();
std::set<C>::iterator itrSetEnd = _setData.end();
while(itrSet != itrSetEnd)
{
deque_Data.push_back(*itrSet);
++itrSet;
}
}
int main()
{
A* pA = new A();
std::set<C> setData;
C mC1(5,10);
C mC2(10,20);
C mC2(30,40);
C.insert(mC1);
C.insert(mC2);
C.insert(mC3);
pA->UpdateDataSet(setData);
return 0;
}
Here C is a Class which contains two integers. The above code working fine as I expected. But the problem is when I do a profiling on my code using valgrind memcheck, it points out some possibly lost data near the code block
deque_Data.push_back(*itrSet);
The valgrind output is as below.
==3469== 1,032,640 bytes in 180 blocks are possibly lost in loss record 1,337 of 1,346
==3469== at 0x4006355: operator new(unsigned int) (vg_replace_malloc.c:214)
==3469== by 0x46B92AF: __gnu_cxx::new_allocator<C*>::allocate(unsigned int, void const*) (new_allocator.h:88)
==3469== by 0x46B92E7: std::_Deque_base<C, std::allocator<C> >::_M_allocate_map(unsigned int) (stl_deque.h:424)
==3469== by 0x46B94F9: std::deque<C, std::allocator<C> >::_M_reallocate_map(unsigned int, bool) (deque.tcc:750)
==3469== by 0x46B960B: std::deque<C, std::allocator<C> >::_M_reserve_map_at_back(unsigned int) (stl_deque.h:1444)
==3469== by 0x46B96C5: std::deque<C, std::allocator<C> >::_M_push_back_aux(C const&) (deque.tcc:348)
==3469== by 0x46B9822: std::deque<C, std::allocator<C> >::push_back(C const&) (stl_deque.h:1045)
==3469== by 0x46B6B09: A::UpdateDataSet(std::set<C, std::less<C>, std::allocator<C> >&)
Can someone please help me to find out the memory issue here. Is this valgrind output really mean a memory leak?
Upvotes: 0
Views: 914
Reputation: 24626
There are two reasons I can think of why the memory allocated by a deque might not get deallocated, assuming a correct implementation of your standard library:
reinterpet_cast
/C-style casts might give you access to memory locations where the deque stores its private members, e.g. pointers to allocated memory. If you mess around with those private members in any way, deque might not be able to deallocate its dynamically allocated memory, leading to memleaks. Normally such agressive acts lead to access violations of many kinds, so you would observe rather crashes than just memleaks.deque*
and allocated the deque itself on the free store/heap (see below). Reason for a missing call of A's destructor might be one or more of the following:
A()
)free()
instead of delete: free only frees the memory but does not call any destructors. Never match new and free, even better try not to use malloc/free with C++ objects unless you are very careful and know what you do (placement new...)goto
's, since most compilers emit errors if you violate object lifetime boundaries with goto. Nevertheless, try not to use goto
in C++, as there are other features you can use. The only "jumping" i could emagine here is longjmp
, which is a C feature that does not respect scope boundaries and thus ignores the need for destructor calls, amongst others. Never use longjmp
in C++ code.If anybody can think of more reasons for the memleak, missing destructor calls or others, give me a hint, I'll edit this answer :-)
PS: I just saw I missed the "see below" part - so what's the deal if you have a deque*
in A instead of a deque
? In that case, A is responsible for correctly constructing and destructing the deque, meaning
- call new whenever you need to create the queue
- call delete at least in the destructor
- handle especially copy/move assignment and copy/move construction correctly
However, if you have a deque*
and messed up the pointer handling you should see another memleak, pointing you to any of the new deque
calls you will have.
Upvotes: 1
Reputation:
You are missing something in your example, there is no memory leak.
I complied and ran this code
#include <set>
#include <deque>
class C
{
public:
C (int a, int b)
: m_a (a)
, m_b (b)
{
}
bool operator <(const C& c) const
{
return m_a < c.m_a || (m_a == c.m_a && m_b < c.m_b);
}
private:
int m_a;
int m_b;
};
class A
{
public:
A(){};
~A() {};
void UpdateDataSet(std::set<C>& _setData);
private:
std::deque<C> deque_Data;//contains ohlc data for the symbol
};
void A::UpdateDataSet(std::set<C>& _setData)
{
std::set<C>::iterator itrSet = _setData.begin();
std::set<C>::iterator itrSetEnd = _setData.end();
while(itrSet != itrSetEnd)
{
deque_Data.push_back(*itrSet);
++itrSet;
}
}
int main()
{
A* pA = new A();
std::set<C> setData;
C mC1(5,10);
C mC2(10,20);
C mC3(30,40);
setData.insert(mC1);
setData.insert(mC2);
setData.insert(mC3);
pA->UpdateDataSet(setData);
delete pA;
return 0;
}
valgrind doesn't report anything suspicious, as expected
Upvotes: 1