c++ - 是否从等待返回到悬空的“this”实例的未定义行为?
问题描述
以下代码是未定义的行为还是合法的?
#include <thread>
#include <functional>
#include <atomic>
std::atomic<bool> b{false};
// these are defined in some other file.
// actual implementation is not important for this question here
Handle insideFoo, continueFoo; // some type defined somewhere
void Wait(Handle h); // blocks current thread until someone calls Continue(h)
void Continue(Handle h); // makes any thread blocked in Wait(h) continue
struct S {
int i;
void foo() {
i = 23; // <- sample code that uses "this" pointer
Continue(insideFoo); // <- signal main that we are inside S::foo and past all "this" usage
Wait(continueFoo); // <- block until main tells us to continue
// here, "this" is destroyed (see main function)
if (b) return; // <- b is not instance variable, so its not an access to dangling "this"
i = 42; // <- other sample code that uses "this" pointer
}
};
int main() {
S* s = new S;
continueFoo.lock();
std::thread t(std::bind(&S::foo, s));
Wait(insideFoo); // wait until S::foo is finished accessing "this"
delete s;
b = false;
Continue(continueFoo); // let s.foo continue.
}
问题是关于S::foo
已经开始并且保证在函数内部不再访问this
指针的指令的事实。此外,这个“内部指令foo()
”受到内存栅栏的保护(std::mutex
在我的示例中)。下面的代码if(b)
也被围起来(事实上b
是 a std::atomic<bool>
),对吧?
对我来说,返回到 this 指针悬空的成员函数仍然感觉有点可疑,但我找不到任何理由说明这应该是明确的“未定义行为”。它没有访问s->foo()
(因为函数已经启动)并且在检查后立即返回以b
保证不会发生其他 this 访问。
那么这是允许的吗?是否纯粹从子函数(Wait(continueFoo)
在这种情况下)返回到成员函数,其 this 悬空已经未定义的行为?我在标准中找不到任何参考。
PS:这是我在未定义行为( Undefined behavior)中第二次尝试在其他线程运行不访问“this”的成员函数时删除“this”的问题?. 我不认为它与链接的问题相同。C++ 中的这种未定义行为是否从悬空指针调用函数,因为在删除它后我没有取消引用s
。我明确地首先调用s->foo
然后删除实例(并且我保证线程已经启动)。
解决方案
Richard Critten 在评论中发布了正确的方向:
问题可以简化为:
struct foo { void bar() { delete this; /* what can I do here? */ } };
——理查德·克里顿”
这delete this
是一个众所周知的现象,甚至在 isocpp 常见问题解答中明确回答:https ://isocpp.org/wiki/faq/freestore-mgmt#delete-this
所以正确的答案基本上是:“是的,它的定义。小心点,好吗?”
推荐阅读
- cefsharp - 使用 CefSharp 检测某些关键字时如何停止连续加载
- jquery - vtiger 7,查询限制/偏移/计数不起作用
- mysql - 如何在 GCloud SQL 实例上运行迁移?
- angular - 将 bootsrap 模板集成到我的 Angular 项目中的问题:当我添加样式文件时,应用程序停止工作
- node.js - MS Bot 框架,将来自 auth0 的用户 ID 与对话状态相关联
- angular - 'any[]' 类型的参数不可分配给 '(value: [any, Campaign[]]) => void' 类型的参数
- google-app-engine - 谷歌云任务孤立
- kubernetes - Kubernetes:使用 CustomResourceDefinition + 运算符创建数据库访问机密
- c# - 当 TextBox 值更改时如何更新标签?
- javascript - 我可以为图表标题中的每一行文本指定不同的字体大小吗?