我正在发送一个 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/