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();

問題は、このような場合、コールバックでユーザーを削除すると、ユーザーが既に削除されているため、アプリケーションがクラッシュすることです。もう 1 つの問題は、コールバックがユーザーを削除することですが、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();

リクエストでそのオブジェクトをもう使用したくない場合は、オブジェクトを使用しないように、サーバーへの保存アクションを「キャンセル」する機能を提供する必要があります。


もう 1 つのオプションは、スマート ポインターを使用することです。メイン コードで、オブジェクトを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_thisweak_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 に答える