簡體   English   中英

線程開始執行后,C++ std::thread callable 的 object 指針能否失效?

[英]Can C++ std::thread callable's object pointer be invalidated after the thread begins execution?

我有這段代碼...

一個非靜態成員方法(作為線程的可調用方法):

void Object::unregister()
{
   ...
}

和這樣的析構函數:

Object::~Object()
{
  std::thread cleanup(&Object::unregister, this);
  cleanup.detach();
}

我看到的一個問題是我正在運行一個帶有參數this的線程,當析構函數完成時它變得無效,所以我認為這是危險的,因為我沒有任何保證,清理線程已經開始 - 這是我的子問題 -如果在unregister的調用完全完成之前this將失效(析構函數完成)是安全的(換句話說,如果它已經開始,但沒有完全完成)可以嗎?

我會說答案是否定的,因為this指針的副本與 callable 一起使用,但我不確定應用程序的行為,就像它不介意並且一切正常。

如果線程剛剛開始但還沒有結束沒問題,有沒有辦法知道線程已經在運行? 調用joinable()是否會在線程已經執行時返回true ,或者它可以在線程執行開始之前返回true

有什么方法可以安全地做到這一點並確保可調用的&Object::unregister並且this不會失效,因為Object同時被破壞了?

如果在取消注冊的調用完全完成之前這將失效(析構函數完成)是安全的(換句話說,如果它已經開始,但沒有完全完成)可以嗎?

不,這不安全。

考慮以下 C 代碼:

void Object_unregister(void* obj)
{
    Object* this = (Object*)obj;
    fclose(this->file_handle);
    while (this->ref_counter > 0) {
        fclose(this->ref_array[this->ref_counter]->handle);
        free(this->ref_array[this->ref_counter]);
        this->ref_array[this->ref_counter] = NULL;
        --this->ref_counter;
    }
}

void destroy_Object(Object** this)
{
    pthread_t thread;
    pthread_create(&thread, NULL, &Object_unregister, (void*)*this);
    pthread_detach(&thread);
    free(*this);
    *this = NULL;
}

這就是你的 C++ 代碼在做的最基本的事情。 在此代碼中,我們創建線程,然后將其分離,然后立即釋放 Object 所在的Object空間。 這樣,不能保證Object_unregister function 中的this指針將指向傳遞給它的相同Object

有一個(一般)保證,線程 function 仍將指向與創建線程相同的 function 指針地址,並且它將一直運行到this指針將指向與調用 function 時相同的 memory 地址。

但...

this可能指向0xABADCAFE並且this->file_handle將指向this + sizeof(Object::file_handle) ,但是如果您刪除了 object,那么該地址的實際內容可能不再指向Object的有效引用類型。

It could point to some random bit of encryption code, or a new function, or just about anything, but it could still point to the object that was originally there if that memory space was not reallocated by the kernel.

所以不,這不安全。

有什么方法可以安全地做到這一點並確保可調用的&Object::unregister並且this不會失效,因為Object同時被破壞了?

好吧,這取決於您的Object::unregister代碼在代碼的 rest 上下文中實際執行的操作。 目前還不清楚為什么要線程化析構函數並且不只是調用this->unregister(); 在析構函數中,例如:

Object::~Object()
{
    this->unregister();
}

這與您在代碼上下文中獲得的一樣安全。

但是,如果還有其他事情必須以線程方式完成,您可以做許多架構上的事情來線程化 object 的破壞,從 static 值到鎖定機制,但基本上您需要做的是復制您需要unregister的特定值,以便它們在您的線程代碼中保持有效。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM