简体   繁体   English

分配包含stl向量的结构时发生内存泄漏

[英]Memory leaks when allocating struct containing stl vector

I want to allocate memory for a struct that contains std::vector . 我想为包含std::vector的结构分配内存。 After allocating it, I will push_back some data to it. 分配它之后,我将push_back一些数据到它。 After all, I need to destroy my allocated struct. 毕竟,我需要销毁分配的结构。 I want to know how can it be done with no memory corruption. 我想知道如何在没有内存损坏的情况下完成此操作。

Here is my code: 这是我的代码:

typedef struct my_struct_t{

    int a, b;
    vector<unsigned> vec;

}
} MYSTRUCT;


int main(int argc, const char * argv[])
{

    MYSTRUCT* ptr_s =  new MYSTRUCT;

    for(int i = 0 ; i < 100 ; i++){
        ptr_s->vec.push_back(i);
    }
    ptr_s->vec.clear();
    delete ptr_s;

    return 0;
}

I tried to use clear as it is supposed to call destructor. 我试图使用clear因为它应该称为析构函数。 But after valgrind -ing my code, there are still some blocks reachable. 但是在valgrind -ing我的代码之后,仍然有一些可到达的块。 I also tried to deallocate vector using this: 我也尝试使用以下方法释放向量:

vector<unsigned>().swap(ptr_s.vec)

But with no success. 但是没有成功。

output of `valgrind': valgrind的输出:

==52635== HEAP SUMMARY:
==52635==     in use at exit: 10,360 bytes in 5 blocks
==52635==   total heap usage: 147 allocs, 142 frees, 25,198 bytes allocated
==52635== 
==52635== LEAK SUMMARY:
==52635==    definitely lost: 0 bytes in 0 blocks
==52635==    indirectly lost: 0 bytes in 0 blocks
==52635==      possibly lost: 0 bytes in 0 blocks
==52635==    still reachable: 10,360 bytes in 5 blocks
==52635==         suppressed: 0 bytes in 0 blocks
==52635== Reachable blocks (those to which a pointer was found) are not shown.
==52635== To see them, rerun with: --leak-check=full --show-leak-kinds=all

Thank you everyone in advance. 预先谢谢大家。

update: 更新:

I noticed that the source of memory corruption in my application is in somewhere else. 我注意到应用程序中内存损坏的根源在其他地方。 So I added an update. 所以我添加了一个更新。 Here is the new code: 这是新代码:

MYSTRUCT* ptr_s1 =  new MYSTRUCT;
MYSTRUCT* ptr_s2 =  new MYSTRUCT;

for(int i = 0 ; i < 100 ; i++){
    ptr_s1->vec.push_back(i);
}


memcpy(ptr_s2 , ptr_s1, sizeof(*ptr_s1));

delete ptr_s1;
delete ptr_s2;  // here I get seg fault

return 0;

As soon as deleting ptr_s2 , seg fault happens. 一旦删除ptr_s2 ,就会发生段错误。

Update : proper way, based on the accepted answer: 更新 :基于接受的答案的正确方法:

typedef struct my_struct_t{

    int a, b;
    vector<unsigned> vec;
    inline my_struct_t operator=(const my_struct_t &s ){
       a = s.a;
       b = s.b;
       vec = s.vec;
       return s;
    }
} MYSTRUCT;

MYSTRUCT* ptr_s1 =  new MYSTRUCT;
MYSTRUCT* ptr_s2 =  new MYSTRUCT;

for(int i = 0 ; i < 100 ; i++){
    ptr_s1->vec.push_back(i);
}

// no memcpy
// memcpy(ptr_s2 , ptr_s1, sizeof(*ptr_s1));
*ptr_s2 = *ptr_s1;

delete ptr_s1;
delete ptr_s2;  // no more sget seg fault

return 0;

You don't need to call std::vector::clear or do something else, the destructor will get called when you delete it via delete ptr_s; 您不需要调用std::vector::clear或执行其他操作,通过delete ptr_s;删除析构函数时,该析构函数将被调用delete ptr_s; .

The still reachable matter is explained in Valgrind FAQ . 在Valgrind FAQ中解释了still reachable解决的问题

My program uses the C++ STL and string classes. 我的程序使用C ++ STL和字符串类。 Valgrind reports 'still reachable' memory leaks involving these classes at the exit of the program, but there should be none. Valgrind在程序退出时报告了涉及这些类的“仍可到达”的内存泄漏,但应该没有泄漏。

First of all: relax, it's probably not a bug, but a feature. 首先:放松,这可能不是错误,而是功能。 Many implementations of the C++ standard libraries use their own memory pool allocators. C ++标准库的许多实现都使用它们自己的内存池分配器。 Memory for quite a number of destructed objects is not immediately freed and given back to the OS, but kept in the pool(s) for later re-use. 大量销毁对象的内存不会立即释放并交还给OS,而是保留在池中供以后重用。 The fact that the pools are not freed at the exit of the program cause Valgrind to report this memory as still reachable. 程序退出时未释放池的事实导致Valgrind报告此内存仍可访问。 The behaviour not to free pools at the exit could be called a bug of the library though. 但是,在出口处不释放池的行为可以称为库的错误。

Update: 更新:

Briefly, don't copy classes with memcpy , if you use memcpy to copy a class object whose destructor deletes a pointer within itself (std::vector member in your case), you will end up with double delete when the second instance of the object is destroyed. 简单地说,不要复制类与memcpy ,如果你使用memcpy复制一个类的对象,它的析构函数删除其自身内(在您的案件的std ::矢量成员)的指针,你将最终获得双删除时的第二个实例对象被破坏。

The right way is copy/move constructor and/or assignment operator for classes. 正确的方法是复制/移动类的构造函数和/或赋值运算符。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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