gpt4 book ai didi

c++ - 线程开始执行后,C++ std::thread callable 的对象指针可以失效吗?

转载 作者:行者123 更新时间:2023-12-03 12:58:06 26 4
gpt4 key购买 nike

我有这段代码...
一个非静态成员方法(作为线程的可调用方法):

void Object::unregister()
{
...
}
和这样的析构函数:
Object::~Object()
{
std::thread cleanup(&Object::unregister, this);
cleanup.detach();
}
我认为的一个问题是我正在运行一个带有参数 this 的线程。当析构函数完成时它变得无效,所以我认为这是危险的,因为我没有任何保证,清理线程已经开始 - 这是我的子问题 - 如果 this 是安全的将在调用 unregister 之前失效(析构函数完成)完全完成 (换句话说,如果它已经开始,但没有完全完成,是否可以) ?
我会说答案是 作为 this 的拷贝指针与 callable 一起使用,但我不确定应用程序的行为,就像它不介意并且一切正常。
如果线程刚刚启动还没有完成,那么有什么方法可以知道线程已经在运行了吗?调用 joinable() 的用法还我 true仅当线程已经在执行时或者它可以返回 true在线程开始执行之前?
有什么办法可以安全地做到这一点,并确保可调用 &Object::unregister this 不会失效,因为 Object 同时被摧毁?

最佳答案

is safe if this would be invalidated (destructor finishes) before the call to unregister finishes completely (in other words is it ok, if it already started, but did not finish completely)?


不,这不安全。
考虑以下 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 所在的内存空间。这样,无法保证 this 函数中的 Object_unregister 指针将指向传递给它的同一个 Object
有一个(一般)保证线程函数仍然指向创建线程时使用的相同函数指针地址,并且它将一直运行直到该函数完成,并且在上面的代码中,有一个保证 this指针将指向与调用函数时相同的内存地址。
但 ... this 可以指向 0xABADCAFE 并且 this->file_handle 将指向 this + sizeof(Object::file_handle) ,但是如果你已经删除了对象,那么实际上是 处的 可以指向一个有效的 的地址为 a504077919 的 a50404040404040404040404000
它可以指向一些随机的加密代码,或者一个新函数,或者任何东西,但是如果内核没有重新分配内存空间,它仍然可以指向最初存在的对象。
所以不,它不安全。

Is there any way how to do it safe and be sure that callable &Object::unregister and this will not be invalidated, because Object was destroyed meanwhile?


好吧,这取决于您的 Object 代码在其余代码的上下文中实际执行的操作。目前还不清楚为什么要线程化析构函数,并且不只是在析构函数中调用 Object::unregister,例如:
Object::~Object()
{
this->unregister();
}
这与您在代码上下文中所能获得的一样安全。
但是如果有其他事情必须以线程的方式完成,你可以做很多架构的事情来线程化对象的销毁,从静态值到锁定机制,但本质上你需要做的是复制您需要 this->unregister(); 的特定值,以便它们在您的线程代码中保持有效。

关于c++ - 线程开始执行后,C++ std::thread callable 的对象指针可以失效吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66589173/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com