0

我正在开发一个 C++ 应用程序,我需要将 std::set 的内容复制到 std::deque。类似于我在我的应用程序中所做的事情如下。(这是简化版)

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;
}

这里 C 是一个包含两个整数的类。上面的代码按我的预期工作得很好。但问题是当我使用 valgrind memcheck 对我的代码进行分析时,它指出了代码块附近可能丢失的一些数据

deque_Data.push_back(*itrSet); 

valgrind 输出如下。

==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> >&)

有人可以帮我找出这里的内存问题。这个 valgrind 输出真的意味着内存泄漏吗?

4

3 回答 3

2

您没有在 main 末尾执行“删除 pA”...

于 2012-11-29T09:42:28.900 回答
1

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

于 2012-11-29T11:19:29.923 回答
1

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:

  1. Violently accessing the deque's internals. Using memset/memcpy or 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.
  2. Missing deque destructor call. If for any reason a deque's destructor gets not called, it has no opportunity to "clean up", i.e. deallocate its owned dynamic memory, leading to said memleaks. In Your case, the deque destructor automatically gets called by A's destructor, unless you have a 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:
    • Missing delete: delete calls the destructor of an object and releases the memory where the object had been. In that case, you should see another memleak, pointing where the object was allocated and created (in your sample code the new A())
    • Calling 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...)
    • "Jumping" out of code. I you somehow "jump" out of scopes, the compiler might not be able to do the automated destructor calls at the end of the scope blocks. This does not apply for exceptions, because compilers know what to do and how to clean up. This should not apply for 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.

于 2012-11-29T11:07:31.803 回答