简体   繁体   中英

c++ memory leak when using std::string in shared memory array

I have this class

class LayoutEntry
{
  unsigned int id_;
  string name_;  
  bool isInput_;
};

The copy constructor looks like this:

LayoutEntry(const LayoutEntry &other)
        : id_(other.id_),
        name_(other.name_), 
        isInput_(other.isInput_)
    {
    }

Objects of this class are put inside a map within another class

class DataLayoutDescription 
{
    unsigned int sz_;
    set<LayoutEntry, SortByOffset> impl;

    // HERE!!!
    map<unsigned int, LayoutEntry> mapById;

The copy constructor of this class looks like this:

DataLayoutDescription::DataLayoutDescription(const DataLayoutDescription &other)
    :sz_(other.sz_), impl(other.impl), mapById(other.mapById)
{   
}

Now the question:

  • I Get a memory leak for each LayoutEntry when run like printed
  • If I remove mapById(other.mapById) in the copy constructor of DataLayoutDescription then there is no memleak
  • If I remove name_(other.name_), The memory leaks are also gone

Why?

EDIT

For Testing I use BOOST::UnitTest at the end I get a memory leak dump

C:\wc\05_EAPGit\Debug>EapLibTest.exe --run-test=SharedVectorTest
Running 7 test cases...

*** No errors detected
Detected memory leaks!
Dumping objects ->
{1378} normal block at 0x005815C0, 16 bytes long.
 Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
{1377} normal block at 0x00581580, 16 bytes long.
 Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
{1376} normal block at 0x00581540, 16 bytes long.
 Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.

Possible Reason? I persist the DataLayoutDescription in a shared memory area using this method

void DataLayoutDescription::Save(LayoutEntry *les, unsigned int maxEntries) const
{
    int n = std::max(impl.size(), maxEntries);
    int i = 0;
    for (DataLayoutDescription::iterator it = begin(); it != end(); ++it)
    {
        les[i] = *it;  // Source of memory leak here???
        ++i;
    }
}

I dereference the iterator ant store a copy of this in the array that is located in the shared memory region. Is there something wrong? The shared memory is deleted on exit.

Furhter Trackdown The class LayoutEntry is placed in an array within a shared memory area and contains a string. The reason for the memory leak is that the string gets resized. Thus it allocates more memory on the heap. Now I guess that this memroy will not be freed since the original memory is located in the shared memory. Could this be the reason? Next thing I will try to remove the string and replace it with an char array of fixed length.

... after several minutes

This was it. After replacing the string with a fixed array of char the memory leak dissapeared. Hope this helps someone.

It looks like the memory leak that was introduced in Visual Studio 2010 C++ standard library, fixed with SP1 . If it's your compiler (without SP1) that's certainly the problem.

See also those answers : STL container leak

Assuming that when you say you have a memory leak, you mean some checker like Purify or valgrind is telling you so, the most likely scenario is that somehow you're leaking LayoutEntry objects, NOT string objects directly. I got bitten by this once and got confused because my own object was getting leaked, but the leak was tagged (by valgrind) to std::string which made it harder to find.

Alternately it may just be detecting a growth. Did you try doing a clear on your map prior to exiting?

The reason for the leak was the LayoutEntry class that stores a string. The base object (before modification) was placed in an array within a shared memory area. After altering the string a resize operation was performed, this memory was lost. After replacing the string by an array of chars (fixed length) the memory leak went away. I am happy now but ask myself if the string class does something wrong, or is there a way to put a custom allocator into the std::string? I will not need this because I will go with the char array but I am just curious if something like this would work and weather I am right with this assumtions?

This is the modified class

class LayoutEntry
{
  unsigned int id_;
  char name_[128];  
  bool isInput_;
};

Thanks everybody for your help! The tips for debugging the memory leak helped me a lot.

If you have consistent allocation numbers in the leaks, you can set the debug memory allocator to break at that specific allocation using _CrtSetBreakAlloc .

http://msdn.microsoft.com/en-us/library/4wth1ha5.aspx

For example, adding _CrtSetBreakAlloc(1378) to your code will cause a debug break when allocating block number 1378. You can then use the debugger to follow the code back to the caller.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM