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

Memory leaks when allocating struct containing stl vector

本文关键字:内存 泄漏 结构 包含 stl 向量 分配      更新时间:2023-10-16

我想为包含std::vector的结构分配内存。在分配它之后,我将向它push_back一些数据。毕竟,我需要销毁我分配的结构。我想知道在没有内存损坏的情况下如何做到这一点。

这是我的代码:

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

我尝试使用clear,因为它应该调用析构函数。但是在valgrind修改我的代码之后,仍然有一些块可以访问。我还尝试使用以下方法解除分配矢量:

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

但没有成功。

"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

提前感谢大家。

更新:

我注意到我的应用程序内存损坏的原因在其他地方。所以我添加了一个更新。这是新代码:

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;

一旦删除ptr_s2,seg故障就会发生。

更新:正确的方式,基于已接受的答案:

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;

您不需要调用std::vector::clear或执行其他操作,当您通过delete ptr_s;删除它时,将调用析构函数。

关于still reachable问题,请参阅Valgrind常见问题解答。

我的程序使用C++STL和字符串类。Valgrind报告的出口处涉及这些类的"仍然可访问"内存泄漏程序,但应该没有。

首先:放松,这可能不是一个bug,而是一个特性。许多的C++标准库的实现使用它们自己的内存池分配器。相当多的析构函数对象的内存是没有立即释放并返回给操作系统,而是保存在池以备日后重复使用。事实上,在程序的退出导致Valgrind将此内存报告为静止可达。在出口处不释放水池的行为可以称为不过是图书馆的一个bug。

更新:

简单地说,不要使用memcpy复制类,如果使用memcpy复制类对象,该类对象的析构函数会删除其内部的指针(在您的情况下为std::vector成员),那么当对象的第二个实例被销毁时,您将以双删除结束。

正确的方法是复制/移动类的构造函数和/或赋值运算符。