在共享内存数组中使用std :: string时c ++内存泄漏

时间:2011-05-17 13:15:31

标签: c++ memory-leaks

我有这个班级

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

复制构造函数如下所示:

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

此类的对象放在另一个类

中的地图内
class DataLayoutDescription 
{
    unsigned int sz_;
    set<LayoutEntry, SortByOffset> impl;

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

此类的复制构造函数如下所示:

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

现在的问题是:

  • 运行时打印
  • 时,每个LayoutEntry都会出现内存泄漏
  • 如果我在DataLayoutDescription的复制构造函数中删除mapById(other.mapById),那么就没有memleak
  • 如果我删除name_(other.name_),内存泄漏也消失了

为什么?

修改

对于测试我最后使用BOOST :: UnitTest我得到了内存泄漏转储

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.

可能的原因? 我使用此方法将DataLayoutDescription保存在共享内存区域

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

我取消引用迭代器ant存储位于共享内存区域的数组中的副本。有什么不对?退出时将删除共享内存。

Furhter Trackdown LayoutEntry类放在共享内存区域的数组中,并包含一个字符串。内存泄漏的原因是字符串调整大小。因此它在堆上分配更多内存。现在我想这个memroy将不会被释放,因为原始内存位于共享内存中。这可能是原因吗?接下来我将尝试删除字符串并将其替换为固定长度的char数组。

......几分钟后

就是这样。用固定的char数组替换字符串后,内存泄漏消失了。希望这有助于某人。

4 个答案:

答案 0 :(得分:4)

看起来像the memory leak that was introduced in Visual Studio 2010 C++ standard library, fixed with SP1。如果是你的编译器(没有SP1)肯定是问题。

另见答案:STL container leak

答案 1 :(得分:3)

假设当你说你有内存泄漏时,你的意思是像Purify或valgrind这样的一些检查器告诉你,最可能的情况是你不知何故泄漏LayoutEntry个对象,而不是{{1}对象直接。我被这个曾经咬过一次而感到困惑,因为我自己的对象被泄露了,但泄漏被(由valgrind)标记为string,这使得它更难找到。

或者它可能只是检测到增长。您是否尝试在退出前在地图上执行std::string

答案 2 :(得分:3)

泄漏的原因是存储字符串的LayoutEntry类。基础对象(修改前)放在共享内存区域内的数组中。更改字符串后,执行了调整大小操作,此内存丢失。在用字符数组(固定长度)替换字符串后,内存泄漏消失了。我现在很开心,但问问自己字符串类是否出错了,或者有没有办法将自定义分配器放入std :: string?我不需要这个,因为我会选择char数组,但我很好奇,如果这样的事情会起作用,天气我对这个问题是对的吗?

这是修改后的课程

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

感谢大家的帮助!调试内存泄漏的技巧对我帮助很大。

答案 3 :(得分:1)

如果泄漏中的分配编号一致,则可以使用_CrtSetBreakAlloc将调试内存分配器设置为在该特定分配处中断。

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

例如,在分配块号1378时,将_CrtSetBreakAlloc(1378)添加到代码中将导致调试中断。然后,您可以使用调试器将代码跟回给调用者。