STL容器泄漏

发布于 2024-10-08 05:14:09 字数 894 浏览 0 评论 0 原文

我使用向量容器来保存包含 3 个 int 和 2 个 std::string 的对象的实例,这是在堆栈上创建的,并从另一个类中的函数填充但运行应用程序通过 deleaker 显示对象中的 std::string 全部泄漏。代码如下:

// Populator function:
void PopulatorClass::populate(std::vector<MyClass>& list) {
    // m_MainList contains a list of pointers to the master objects
    for( std::vector<MyClass*>::iterator it = m_MainList.begin(); it != m_MainList.end(); it++ ) {
        list.push_back(**it);
    }
}

// Class definition
class MyClass {
private:
    std::string m_Name;
    std::string m_Description;
    int m_nType;
    int m_nCategory;
    int m_nSubCategory;
};

// Code causing the problem:
std::vector<MyClass> list;
PopulatorClass.populate(list);

当通过 deleaker 运行时,泄漏的内存位于 std::string 类的分配器中。

我正在使用 Visual Studio 2010 (CRT)。

在展开堆栈并删除向量时,我需要做些什么特殊的事情才能使string正确删除吗?

谢谢, J

I'm using a vector container to hold instances of an object which contain 3 ints and 2 std::strings, this is created on the stack and populated from a function in another class but running the app through deleaker shows that the std::strings from the object are all leaked. Here's the code:

// Populator function:
void PopulatorClass::populate(std::vector<MyClass>& list) {
    // m_MainList contains a list of pointers to the master objects
    for( std::vector<MyClass*>::iterator it = m_MainList.begin(); it != m_MainList.end(); it++ ) {
        list.push_back(**it);
    }
}

// Class definition
class MyClass {
private:
    std::string m_Name;
    std::string m_Description;
    int m_nType;
    int m_nCategory;
    int m_nSubCategory;
};

// Code causing the problem:
std::vector<MyClass> list;
PopulatorClass.populate(list);

When this is run through deleaker the leaked memory is in the allocator for the std::string classes.

I'm using Visual Studio 2010 (CRT).

Is there anything special I need to do to make the strings delete properly when unwinding the stack and deleting the vector?

Thanks,
J

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

嘦怹 2024-10-15 05:14:09

可能是 内存泄漏 std::vector 或类似的内容。

May be Memory leak with std::vector<std::string> or something like this.

浮光之海 2024-10-15 05:14:09

每当您在 STL 实现中遇到奇怪或错误的问题(例如内存泄漏)时,请尝试以下操作

  • 重现您尝试实现的最基本示例。如果它运行时没有泄漏,那么问题出在您填充数据的方式上。 这是最可能的问题根源(我指的是您自己的代码)。

未针对您的特定问题测试简单的动态示例:

#include <string>
#include <sstream>


// Class definition
struct MyClass  { // struct for convenience
    std::string m_Name;
    std::string m_Description;
    int m_nType;
    int m_nCategory;
    int m_nSubCategory;
};


// Prototype of populator function:
void populate(std::vector<MyClass>& list)
{
    const int MAX_TYPE_IDX = 4;
    const int MAX_CATEGORY_IDX = 8;
    const int MAX_SUB_CATEGORY_IDX = 6;

    for( int type_idx = 0; type_idx < MAX_TYPE_IDX ; ++type_idx)
        for( int category_idx = 0; category_idx < MAX_CATEGORY_IDX ; ++category_idx)
             for( int sub_category_idx = 0; sub_category_idx < MAX_SUB_CATEGORY_IDX ; ++sub_category_idx)
             {
                   std::stringstream name_stream;
                   name_stream << "object_" << type_idx << "_" << category_idx << "_" << sub_category_idx ;
                   std::stringstream desc_stream;
                   desc_stream << "This is an object of the type N°" << type_idx << ".\n";
                   desc_stream << "It is of category N°" << category_idx << ",\n";
                   desc_stream << "and of sub-category N°" << category_idx << "!\n";

                   MyClass object;
                   object.m_Name = name_stream.str();
                   object.m_Description = desc_stream.str();
                   object.m_nType = type_idx;
                   m_nCategory = 
                   m_nSubCategory = 
                   list.push_back( object );
             }
}


int main()
{
    // Code causing the problem:
    std::vector<MyClass> list;
    populate(list);

    // memory leak check?
    return 0;
 }
  • 如果您仍然遇到内存泄漏,首先检查这不是泄漏检测软件的误报
  • 如果不是,Google 查找 STL 实现的内存泄漏问题(大部分时间在编译器开发人员网站上)。实施者可能会提供错误跟踪工具,您可以在其中搜索相同的问题和潜在的解决方案。
  • 如果您仍然找不到泄漏的根源,也许尝试使用不同的编译器构建您的项目(如果可以的话),看看它是否具有相同的效果。同样,如果泄漏仍然发生,则问题很可能来自您的代码。

Every time you got a problem with the STL implementation doing something strange or wrong like a memory leak, try this :

  • Reproduce the most basic example of what you try to achieve. If it runs without a leak, then the problem is in the way you fill the data. It's the most probable source of problem (I mean your own code).

Not tested simple on-the-fly example for your specific problem :

#include <string>
#include <sstream>


// Class definition
struct MyClass  { // struct for convenience
    std::string m_Name;
    std::string m_Description;
    int m_nType;
    int m_nCategory;
    int m_nSubCategory;
};


// Prototype of populator function:
void populate(std::vector<MyClass>& list)
{
    const int MAX_TYPE_IDX = 4;
    const int MAX_CATEGORY_IDX = 8;
    const int MAX_SUB_CATEGORY_IDX = 6;

    for( int type_idx = 0; type_idx < MAX_TYPE_IDX ; ++type_idx)
        for( int category_idx = 0; category_idx < MAX_CATEGORY_IDX ; ++category_idx)
             for( int sub_category_idx = 0; sub_category_idx < MAX_SUB_CATEGORY_IDX ; ++sub_category_idx)
             {
                   std::stringstream name_stream;
                   name_stream << "object_" << type_idx << "_" << category_idx << "_" << sub_category_idx ;
                   std::stringstream desc_stream;
                   desc_stream << "This is an object of the type N°" << type_idx << ".\n";
                   desc_stream << "It is of category N°" << category_idx << ",\n";
                   desc_stream << "and of sub-category N°" << category_idx << "!\n";

                   MyClass object;
                   object.m_Name = name_stream.str();
                   object.m_Description = desc_stream.str();
                   object.m_nType = type_idx;
                   m_nCategory = 
                   m_nSubCategory = 
                   list.push_back( object );
             }
}


int main()
{
    // Code causing the problem:
    std::vector<MyClass> list;
    populate(list);

    // memory leak check?
    return 0;
 }
  • If you still got the memory leak, first check that it's not a false-positive from your leak detection software.
  • Then if it's not, google for memory leak problems with your STL implementation (most of the time on the compiler developer website). The implementor might provide a bug tracking tool where you could search in for the same problem and potential solution.
  • If you still can't find the source of the leak, maybe try to build your project with a different compiler (if you can) and see if it have the same effect. Again if the leak still occurs, the problem have a lot of chances to come from your code.
坐在坟头思考人生 2024-10-15 05:14:09

可能与 Alexey 的链接有相同的根本问题。发布的版本已损坏 basic_string 的移动代码。 MS抛弃了我们VC10用户,所以你必须自己修复它。在 xstring 文件中,您有以下内容:

_Myt& assign(_Myt&& _Right)
    {        // assign by moving _Right
    if (this == &_Right)
        ;
    else if (get_allocator() != _Right.get_allocator()
        && this->_BUF_SIZE <= _Right._Myres)
        *this = _Right;
    else
        {        // not same, clear this and steal from _Right
        _Tidy(true);
        if (_Right._Myres < this->_BUF_SIZE)
            _Traits::move(this->_Bx._Buf, _Right._Bx._Buf,
                _Right._Mysize + 1);
        else
            {        // copy pointer
            this->_Bx._Ptr = _Right._Bx._Ptr;
            _Right._Bx._Ptr = 0;
            }
        this->_Mysize = _Right._Mysize;
        this->_Myres = _Right._Myres;

        _Right._Mysize = 0;
        _Right._Myres = 0;
        }
    return (*this);
    }

注意最后一个

_Right._Myres = 0;

这应该只在最后一个条件下发生,因为短期情况下 _Right 最好不要管。

由于容量设置为 0 而不是 15,当您分配另一个小字符串时,其他代码将在函数 Grow() 中进行意外分支,并分配一块内存,只是为了用直接字符串内容来践踏指针。

Probably same root issue as Alexey's link. The shipped version has broken move code for basic_string. MS abandoned us VC10 users, so you must fix it yourself. in xstring file you have this:

_Myt& assign(_Myt&& _Right)
    {        // assign by moving _Right
    if (this == &_Right)
        ;
    else if (get_allocator() != _Right.get_allocator()
        && this->_BUF_SIZE <= _Right._Myres)
        *this = _Right;
    else
        {        // not same, clear this and steal from _Right
        _Tidy(true);
        if (_Right._Myres < this->_BUF_SIZE)
            _Traits::move(this->_Bx._Buf, _Right._Bx._Buf,
                _Right._Mysize + 1);
        else
            {        // copy pointer
            this->_Bx._Ptr = _Right._Bx._Ptr;
            _Right._Bx._Ptr = 0;
            }
        this->_Mysize = _Right._Mysize;
        this->_Myres = _Right._Myres;

        _Right._Mysize = 0;
        _Right._Myres = 0;
        }
    return (*this);
    }

Note the last

_Right._Myres = 0;

that should happen only under the last condition, for the short case _Right should better be left alone.

As the capacity is set to 0 instead of 15, other code will take unintended branch in function Grow() when you assign another small string and will allocate a block of memory just to trample over the pointer with the immediate string content.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文