c++ - 在回调函数中删除对象

标签 c++ oop pointers memory-management dangling-pointer

我正在发送一个 HTTP 请求来保存/更新服务器上的数据。请求是异步发出的,并在完成时调用回调函数。一切正常,除了有时应用程序在回调中崩溃。

这就是我正在做的:

user = new User();
user->saveOnServer();
user->zombie = true;  // Mark the user that it needs to be deleted in the callback.

User 中,我有一个 saveOnServer() 方法:

void User::saveOnServer(){
    Request *request = new Request();

    // Send request to the server and register the callback.
    request ->setCallback(&userCallback, (void*)this);
}

回调:

void userCallback(void *data){
    User *user = (User*)data;

    // Do something here.
    // Delete user if it's a zombie.
    if(user->zombie)
        delete user;
}

有时,我需要在向服务器发送请求后创建一个新用户:

user = new User();
user->saveOnServer();
user->zombie = true;
// Some code comes here.
if(user)
    delete user;
user = new User();

问题是在这种情况下,应用程序在回调中删除用户时会崩溃,因为它已经被删除了。另一个问题是回调删除了用户,但 main 中的 user 指针仍指向某个地址(悬挂指针),因此我再次尝试删除它。

我不确定在这种情况下管理内存的最佳方式是什么。我有 zombie,因为在某些情况下我不希望回调删除用户。

最佳答案

一旦您调用僵尸用户的 saveOnServer,该请求就是该用户对象的有效“所有者”。不要自己释放它,因为还有其他东西仍然打算使用它并稍后删除它。

事实上,如果服务器 Action 可以异步返回,那么用户对象随时都有可能被销毁。您应该从其他代码中完全停止使用它。您已将对该对象的控制权授予请求,并且您必须停止从其他任何地方使用它:

user = new User();
user->zombie = true; // set *before* transferring ownership to server
user->saveOnServer();
user = NULL;
//some code comes here
user = new User();

如果您不想让请求再使用那个对象,那么您需要提供一些工具来“取消”保存在服务器上的操作,以便它不再使用该对象。


另一种选择是使用智能指针。在您的主代码中,将对象存储在 shared_ptr 中。在请求对象中,将其存储在 weak_ptr 中。这样,如果您的主代码想要销毁用户对象,它可以简单地调用 user.reset()。然后,如果回调尝试使用 weak_ptr,它将发现指向的对象不再可用。使用智能指针时,两个 函数都不应使用delete。指针对象将为您管理用户的生命周期。

shared_ptr<User> user = make_shared<User>()
user->saveOnServer();
//some code comes here
user.reset(new User());

saveOnServer函数中,使用shared_from_this为对象创建一个weak_ptr:

void User::saveOnServer(){
  Request *request = new Request();

  //send request on server and register the callback
  weak_ptr<User> self(shared_from_this());
  request ->setCallback(&userCallback, self);
}

在回调中,使用 weak_ptr:

void userCallback(weak_ptr<User> data){
  shared_ptr<User) user = data.lock();
  if (!user)
    return;

  //do something here
}

关于c++ - 在回调函数中删除对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10708340/

相关文章:

c++ - 光线追踪锥。判别式给出 -ve 值,因此没有交叉点

c++ - 在数组末尾添加一个字符串?

c++ - 未使用的类成员会使代码自行损坏吗?

c - C 中邻接表的图实现

c++ - 在 Qt/C++ 中替代 sleep 函数

c++ - 反向迭代器在优化时返回垃圾

java - Parcelable 对象错误 : Unmarshalling unknown type code *** at offset ***

java - 将标志传递给对象的正确设计模式

c - 使用 calloc 设置双指针

c - C中的双指针问题(下一个单指针,上一个双指针)