c++valgrindstdvectorstdlist

How can I avoid memory leaks coming from std::list and std::vector


I keep fighting memory leaks on a project coded by a former colleague. Valgrind doesn't seem to like std::vector and std::list resize. For example, if I take this method:

void BaseImage::setImageSize(unsigned short width, unsigned short height, unsigned short nbBytePerPixel, const boost::posix_time::ptime& timestamp)
{
    m_timestamp = timestamp;
    bool change = m_width!=width || m_height!=height || m_bytesByPixel!=nbBytePerPixel;
    if(change)
    {
        m_width = width;
        m_height = height;
        m_bytesByPixel = nbBytePerPixel;
        m_stride = m_width * m_bytesByPixel;
        if( m_bufferSize < (m_width * m_height * m_bytesByPixel) + m_headerSize)
        {
            m_bufferSize = m_width * m_height * m_bytesByPixel;
            if (m_data.size()!=(m_headerSize + m_bufferSize))
                m_data.resize(m_headerSize + m_bufferSize);
        }
    }
}

With:

boost::posix_time::ptime m_timestamp;
unsigned short m_width;
unsigned short m_height;
unsigned short m_bytesByPixel;
unsigned int m_stride;
unsigned int m_bufferSize;
unsigned short m_headerSize;
std::vector<unsigned char> m_data;

I get the following leak in my valgrind logfile:

==10093== 614,412 bytes in 1 blocks are possibly lost in loss record 10,043 of 10,050
==10093==    at 0x4C337B3: operator new(unsigned long) (vg_replace_malloc.c:422)
==10093==    by 0x1B9C91: __gnu_cxx::new_allocator<unsigned char>::allocate(unsigned long, void const*) (new_allocator.h:111)
==10093==    by 0x1B9ACF: std::allocator_traits<std::allocator<unsigned char> >::allocate(std::allocator<unsigned char>&, unsigned long) (alloc_traits.h:436)
==10093==    by 0x1B991D: std::_Vector_base<unsigned char, std::allocator<unsigned char> >::_M_allocate(unsigned long) (stl_vector.h:172)
==10093==    by 0x1B934B: std::vector<unsigned char, std::allocator<unsigned char> >::_M_default_append(unsigned long) (vector.tcc:571)
==10093==    by 0x1B8E9C: std::vector<unsigned char, std::allocator<unsigned char> >::resize(unsigned long) (stl_vector.h:692)
==10093==    by 0x1B716C: xawcore::BaseImage::setImageSize(unsigned short, unsigned short, unsigned short, boost::posix_time::ptime const&) (baseimage.cpp:262)
==10093==    by 0x1B6FBD: xawcore::BaseImage::setImageSize(unsigned short, unsigned short, xawcore::PixelType, boost::posix_time::ptime const&) (baseimage.cpp:241)
==10093==    by 0x1B6F1E: xawcore::BaseImage::setImageSize(unsigned short, unsigned short, xawcore::PixelType, xawcore::StreamType, boost::posix_time::ptime const&) (baseimage.cpp:229)
==10093==    by 0x1B6ECE: xawcore::BaseImage::setImageSize(unsigned short, unsigned short, xawcore::PixelType, xawcore::StreamType, bool, boost::posix_time::ptime const&) (baseimage.cpp:223)
==10093==    by 0x21112D: xawcore::OpenNI2Device::acquisition(bool) (openni2device.cpp:314)
==10093==    by 0x218219: xawcore::OnlineStream::acquisitionThread(bool) [clone ._omp_fn.0] (onlinestream.cpp:127)

I also have a similar error when resize is used on a std::list. Is it a false positive? If not, should I use something else than resize or do some steps before using it?


Solution

  • Valgrind does not tell you that resize did something funny.

    It tells you that you forgot to deallocate some memory, and gives you an idea on who allocated them, so you can find the responsible to free them.

    So who should free them? Ah, that would be the vector. And who should free the vector? Ah, that would be your object. And who should free your object? That, only you can tell.