[英]thread stack access from callback after exit
The following code has a callback registered for some clean-up actions.以下代码为某些清理操作注册了一个回调。 As soon as a stop is requested, the callback is invoked from
main
and the thread exits.一旦请求停止,就会从
main
调用回调,线程退出。 The callback then waits a few ms and accesses the vector
on the thread stack which seems invalid since the thread no longer exists.然后回调等待几毫秒并访问线程堆栈上的
vector
,这似乎无效,因为线程不再存在。
valgrind
and g++ -fsanitize=address
do not report any problem and the output of size()
is always as expected. valgrind
和g++ -fsanitize=address
没有报告任何问题并且size()
的输出总是符合预期。 This makes me wonder if it is correct to access the vector on the thread stack as long as request_stop
in main
has not returned.这让我想知道只要
main
中的request_stop
没有返回,访问线程栈上的vector是否正确。
The output is:输出是:
thread finished 140037635319488
call back from: 140037639857984, size 1234
main finished 140037639857984
Note that the vector is accessed after the thread has finished its last line.请注意,在线程完成其最后一行之后访问向量。
Question: is this code undefined behavior?问题:这段代码是未定义的行为吗?
Some relevant quotes from the C++ standard might be helpful C++ 标准中的一些相关引用可能会有所帮助
#include <iostream>
#include <thread>
#include <vector>
#include <stop_token>
#include <chrono>
using namespace std::chrono_literals;
void thread_func(std::stop_token st)
{
std::vector<int> v;
std::stop_callback cb{st, [&v]
{
std::this_thread::sleep_for(1000ms);
for (int i=0; i<1234; ++i)
v.push_back(i);
std::cout << "call back from: " << std::this_thread::get_id()
<< ", size " << v.size() << '\n';
}};
while (!st.stop_requested())
{
// ...
}
std::cout << "thread finished " << std::this_thread::get_id() << '\n';
}
int main()
{
std::stop_source src;
auto t = src.get_token();
auto thr = std::jthread{thread_func, t};
std::this_thread::sleep_for(500ms);
bool b = src.request_stop();
std::cout << "main finished " << std::this_thread::get_id() << '\n';
}
If the callback is being run from another thread (in your case the main thread in the request_stop()
call), then the destructor of std::stop_callback
blocks until that call is finished and destroys the stored callable only afterwards.如果回调是从另一个线程运行的(在您的情况下是
request_stop()
调用中的主线程),则std::stop_callback
的析构函数会阻塞,直到该调用完成,然后才销毁存储的可调用对象。
Because you declared v
before cb
, the vector will be destroyed only after the destructor of cb
returns during the stack unwinding when thread_func
returns after the stop request.因为你在
cb
之前声明了v
,所以当thread_func
在停止请求之后返回时,只有在cb
的析构函数在堆栈展开期间返回之后才会销毁向量。 The thread only exits after the stack unwinding.线程仅在堆栈展开后退出。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.