【问题标题】:Memory leaks when using shared pointers in a vector在向量中使用共享指针时内存泄漏
【发布时间】:2014-08-13 23:55:33
【问题描述】:

我在向向量添加共享指针时一直面临内存泄漏的问题,向量定义如下:

vector<shared_ptr<Recipe>> favorites;

(Recipe 是一个包含 2 个简单字段的简单类)

以下函数用于将食谱添加到用户的收藏夹中:

void User::postRecipe(string recipeName) {
    if (!(*this).isConnected())
        throw UserNotConnectedException();
    if (!(*this).isInGroup())
        throw NotInGroupException();
    shared_ptr<User> owner = server->seekUser((*this).getId());
    shared_ptr<Recipe> recipe(new Recipe(recipeName, owner));
    server->postRecipe((*this).groupName, recipe);
    if (!checkIfRecipeInFavs(favorites, recipeName)) {
        favorites.push_back(recipe);
}

虽然程序可以编译,程序的输出也符合要求,但这个函数的最后一行似乎会导致内存泄漏,如果删除,错误就会消失。

有什么想法吗?提前致谢。

食谱.h:

class Recipe
{
    string name;
    shared_ptr<User> owner;
public:
    Recipe(string name, shared_ptr<User> owner):name(name),owner(owner){};
    ~Recipe(){};
    string getName();
    shared_ptr<User> getOwner();
};

配方.cpp:

string Recipe::getName(){
    return name;
}
shared_ptr<User> Recipe::getOwner(){
    return owner;
}

【问题讨论】:

  • '这个函数的最后一行似乎导致了内存泄漏......'你是怎么检测到这个的?
  • 提示:您可以使用this-&gt;member 代替(*this).member。这将使代码更具可读性。
  • 使用 Valgrind,当这条线被删除时,Valgrind 没有检测到错误
  • @NizarElias Recipe 类是否有复制构造函数、赋值运算符或析构函数?如果是,请尝试删除它们(错误可能存在)。另外,如果没有帮助,请发布他们的代码(编辑您的问题并添加代码)。
  • 是什么让您认为将所有这些共享指针保存在favorites 成员中的User 对象本身不是泄漏的根源?您发布的代码具有循环所有权。用户拥有食谱,并且每个食谱在 它的 所有权列表中都有相同的用户。

标签: c++ vector memory-leaks shared-ptr


【解决方案1】:

当您使用另一个共享指针将所有者存储在配方中时,您会创建一个循环引用,这意味着只有在删除用户时才会删除配方,但只有在删除所有配方时才会删除用户。您应该在 Recipe 中使用weak_ptr 来打破循环。

这是因为shared_ptr 使用简单的引用计数来确定何时应该删除它的指针:每当您复制 shared_ptr 时,它的引用计数(与指针对象一起保存在堆上)都会递增,并且无论何时副本被破坏,计数减少。在其析构函数中看到计数达到零的指针将删除该对象。当两个shared_ptrs 相互引用时,计数永远不会低于两个。

【讨论】:

  • 感谢您提供翔实的回答,我现在明白这个问题了,有什么建议可以解决吗?一个简单的替换所有我将代码中的所有shared_ptr 替换为weak_ptr 的地方可以解决这个问题吗?再次感谢!
  • @NizarElias 在处理智能指针时应该考虑所有权。据推测,User 拥有一个Recipe,因此应该持有一个shared_ptr。由于Recipe拥有owner指向的对象,它应该是weak_ptr
猜你喜欢
  • 2023-03-15
  • 2015-05-26
  • 1970-01-01
  • 2013-08-25
  • 2019-04-18
  • 1970-01-01
  • 1970-01-01
  • 2012-09-08
  • 1970-01-01
相关资源
最近更新 更多