0

我正在发送 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();

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

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

4

1 回答 1

3

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

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

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
}
于 2012-05-22T19:12:06.353 回答