std::thread 执行上下文 (c++14)
std::thread context of execution (c++14)
当 std::thread 调用的函数的 in/out 变量在执行期间更改值时出现问题...
函数:
static int func(stThread_t *&pStThread)
参数
pStThread:它是一个结构,具有指向 std::thread 和其他变量(一些标志)
的指针
typedef struct stThread {
stThread() noexcept {...};
stThread(const stThread &cRigth) noexcept {...};
stThread & operator = (const stThread &cRigth) noexcept {...};
std::thread *pThread;
volatile bool bBegin;
volatile bool bEnd;
} stThread_t;
函数func打印参数std::thread的地址
pStThread 和线程 id
func before 1785280 this_id 21968
this_thread::sleep 2 秒后,它再次打印
func afer ... this_id 21968
static int func(stThread_t *&pStThread) {
std::thread::id this_id = std::this_thread::get_id();
long long p_begin = (long long)pStThread;
std::cout << "func before " << std::to_string(p_begin) << " this_id " << this_id << "\n";
std::cout.flush();
pStThread->bBegin = true;
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
this_id = std::this_thread::get_id();
long long p_end = (long long)pStThread;
std::cout << "func afer " << std::to_string(p_end) << " this_id " << this_id << "\n";
std::cout.flush();
pStThread->bEnd = true;
return 1;
};
指向 std::thread 的指针地址已更改(损坏、删除..?)
pStThread 是指针结构列表 pushing_back stThread_t
std::list<stThread_t*> listOfThreads;
listOfThreads.push_back(pStThread);
我阅读了 std::move,但不能使用指针
最后有一个线程 "garbage collector" 正在尝试擦除所有等待执行的线程。
完整代码在这里
#include <string>
#include <list>
#include <vector>
#include <map>
#include <thread>
#include <mutex>
#include <atomic>
#include <iostream>
typedef struct stThread {
stThread() noexcept {
pThread = NULL;
bBegin = false;
bEnd = false;
};
stThread(const stThread &cRigth) noexcept {
this->pThread = cRigth.pThread;
this->bBegin = (bool)cRigth.bBegin;
this->bEnd = (bool)cRigth.bEnd;
};
stThread & operator = (const stThread &cRigth) noexcept {
this->pThread = cRigth.pThread;
this->bBegin = (bool)cRigth.bBegin;
this->bEnd = (bool)cRigth.bEnd;
return *this;
};
std::thread *pThread;
volatile bool bBegin;
volatile bool bEnd;
} stThread_t;
class CMain
{
public:
typedef std::list<stThread_t*> MyList_threads;
MyList_threads listOfThreads;
public:
CMain() {
std::cout << std::boolalpha << "Ex1 is move-constructible? "
<< std::is_move_constructible<stThread_t>::value << '\n'
<< "Ex1 is trivially move-constructible? "
<< std::is_trivially_move_constructible<stThread_t>::value << '\n'
<< "Ex1 is nothrow move-constructible? "
<< std::is_nothrow_move_constructible<stThread_t>::value << '\n'
<< "Ex2 is trivially move-constructible? "
<< std::is_trivially_move_constructible<stThread_t>::value << '\n'
<< "Ex2 is nothrow move-constructible? "
<< std::is_nothrow_move_constructible<stThread_t>::value << '\n';
};
static int func(stThread_t *&pStThread) {
std::thread::id this_id = std::this_thread::get_id();
long long p_begin = (long long)pStThread;
std::cout << "func before " << std::to_string(p_begin) << " this_id " << this_id << "\n";
std::cout.flush();
pStThread->bBegin = true;
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
this_id = std::this_thread::get_id();
long long p_end = (long long)pStThread;
std::cout << "func afer " << std::to_string(p_end) << " this_id " << this_id << "\n";
std::cout.flush();
pStThread->bEnd = true;
return 1;
};
int _createThreads() {
for (int iIdx = 0; (iIdx < 5); iIdx++) {
stThread_t *pStThread = new stThread_t;
pStThread->pThread = new std::thread(&CMain::func,
std::ref(pStThread));
if (pStThread) {
do {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
} while (!pStThread->bBegin);
listOfThreads.push_back(pStThread);
std::string sLog;
sLog = "\nlistOfThreads.push_back " + std::to_string((long long)pStThread) + "\n";
std::cout << sLog;
std::cout.flush();
}
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
return 1;
};
int _main() {
_createThreads();
std::thread thread_collector([=]() {
bool bEnd = false;
MyList_threads::iterator it;
it = listOfThreads.end();
do {
stThread_t *pStThread = NULL;
if (it == listOfThreads.end()) {
it = listOfThreads.begin();
if (it == listOfThreads.end()) bEnd = true;
}
else it++;
if (it != listOfThreads.end()) {
if ((*it)->bEnd) {
pStThread = *it;
listOfThreads.erase(it);
it = listOfThreads.begin();
}
}
if (pStThread) {
if (pStThread->pThread) {
if (pStThread->pThread->joinable()) {
pStThread->pThread->join();
std::cout << " element deleted " << std::to_string((long long)pStThread) << "\n";
std::cout.flush();
}
delete pStThread->pThread;
pStThread->pThread = NULL;
}
delete pStThread;
}
pStThread = NULL;
std::this_thread::sleep_for(std::chrono::milliseconds(1));
} while (!bEnd);
});
if (thread_collector.joinable()) {
thread_collector.join();
}
return 1;
};
};
int main()
{
CMain _main;
_main._main();
return 0;
}
您有一个相当简单的错误,主要与线程无关:
(1) func
对 stThread_t*
进行 引用 。
static int func(stThread_t *&pStThread);
(2) 您传入对 pStThread
的引用
std::thread(&CMain::func,std::ref(pStThread));
(3) 这是一个局部变量,它的生命周期在循环迭代结束后立即结束
for (int iIdx = 0; (iIdx < 5); iIdx++) {
stThread_t *pStThread = new stThread_t;
//...
}
(4) 因此,当您的函数在对象被销毁后尝试访问该对象时,您会得到未定义的行为。 (注意!这里,"the object"指的是有问题的指针,而不是指针指向的对象)
不清楚您为什么坚持通过引用传递 pStThread
;你的函数实际上并没有修改指针(只是指向什么),而且你似乎不打算做任何这样的设备实际上有好处的事情。
当 std::thread 调用的函数的 in/out 变量在执行期间更改值时出现问题...
函数:
static int func(stThread_t *&pStThread)
参数
pStThread:它是一个结构,具有指向 std::thread 和其他变量(一些标志)
的指针typedef struct stThread {
stThread() noexcept {...};
stThread(const stThread &cRigth) noexcept {...};
stThread & operator = (const stThread &cRigth) noexcept {...};
std::thread *pThread;
volatile bool bBegin;
volatile bool bEnd;
} stThread_t;
函数func打印参数std::thread的地址 pStThread 和线程 id
func before 1785280 this_id 21968
this_thread::sleep 2 秒后,它再次打印
func afer ... this_id 21968
static int func(stThread_t *&pStThread) {
std::thread::id this_id = std::this_thread::get_id();
long long p_begin = (long long)pStThread;
std::cout << "func before " << std::to_string(p_begin) << " this_id " << this_id << "\n";
std::cout.flush();
pStThread->bBegin = true;
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
this_id = std::this_thread::get_id();
long long p_end = (long long)pStThread;
std::cout << "func afer " << std::to_string(p_end) << " this_id " << this_id << "\n";
std::cout.flush();
pStThread->bEnd = true;
return 1;
};
指向 std::thread 的指针地址已更改(损坏、删除..?)
pStThread 是指针结构列表 pushing_back stThread_t
std::list<stThread_t*> listOfThreads;
listOfThreads.push_back(pStThread);
我阅读了 std::move,但不能使用指针
最后有一个线程 "garbage collector" 正在尝试擦除所有等待执行的线程。
完整代码在这里
#include <string>
#include <list>
#include <vector>
#include <map>
#include <thread>
#include <mutex>
#include <atomic>
#include <iostream>
typedef struct stThread {
stThread() noexcept {
pThread = NULL;
bBegin = false;
bEnd = false;
};
stThread(const stThread &cRigth) noexcept {
this->pThread = cRigth.pThread;
this->bBegin = (bool)cRigth.bBegin;
this->bEnd = (bool)cRigth.bEnd;
};
stThread & operator = (const stThread &cRigth) noexcept {
this->pThread = cRigth.pThread;
this->bBegin = (bool)cRigth.bBegin;
this->bEnd = (bool)cRigth.bEnd;
return *this;
};
std::thread *pThread;
volatile bool bBegin;
volatile bool bEnd;
} stThread_t;
class CMain
{
public:
typedef std::list<stThread_t*> MyList_threads;
MyList_threads listOfThreads;
public:
CMain() {
std::cout << std::boolalpha << "Ex1 is move-constructible? "
<< std::is_move_constructible<stThread_t>::value << '\n'
<< "Ex1 is trivially move-constructible? "
<< std::is_trivially_move_constructible<stThread_t>::value << '\n'
<< "Ex1 is nothrow move-constructible? "
<< std::is_nothrow_move_constructible<stThread_t>::value << '\n'
<< "Ex2 is trivially move-constructible? "
<< std::is_trivially_move_constructible<stThread_t>::value << '\n'
<< "Ex2 is nothrow move-constructible? "
<< std::is_nothrow_move_constructible<stThread_t>::value << '\n';
};
static int func(stThread_t *&pStThread) {
std::thread::id this_id = std::this_thread::get_id();
long long p_begin = (long long)pStThread;
std::cout << "func before " << std::to_string(p_begin) << " this_id " << this_id << "\n";
std::cout.flush();
pStThread->bBegin = true;
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
this_id = std::this_thread::get_id();
long long p_end = (long long)pStThread;
std::cout << "func afer " << std::to_string(p_end) << " this_id " << this_id << "\n";
std::cout.flush();
pStThread->bEnd = true;
return 1;
};
int _createThreads() {
for (int iIdx = 0; (iIdx < 5); iIdx++) {
stThread_t *pStThread = new stThread_t;
pStThread->pThread = new std::thread(&CMain::func,
std::ref(pStThread));
if (pStThread) {
do {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
} while (!pStThread->bBegin);
listOfThreads.push_back(pStThread);
std::string sLog;
sLog = "\nlistOfThreads.push_back " + std::to_string((long long)pStThread) + "\n";
std::cout << sLog;
std::cout.flush();
}
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
return 1;
};
int _main() {
_createThreads();
std::thread thread_collector([=]() {
bool bEnd = false;
MyList_threads::iterator it;
it = listOfThreads.end();
do {
stThread_t *pStThread = NULL;
if (it == listOfThreads.end()) {
it = listOfThreads.begin();
if (it == listOfThreads.end()) bEnd = true;
}
else it++;
if (it != listOfThreads.end()) {
if ((*it)->bEnd) {
pStThread = *it;
listOfThreads.erase(it);
it = listOfThreads.begin();
}
}
if (pStThread) {
if (pStThread->pThread) {
if (pStThread->pThread->joinable()) {
pStThread->pThread->join();
std::cout << " element deleted " << std::to_string((long long)pStThread) << "\n";
std::cout.flush();
}
delete pStThread->pThread;
pStThread->pThread = NULL;
}
delete pStThread;
}
pStThread = NULL;
std::this_thread::sleep_for(std::chrono::milliseconds(1));
} while (!bEnd);
});
if (thread_collector.joinable()) {
thread_collector.join();
}
return 1;
};
};
int main()
{
CMain _main;
_main._main();
return 0;
}
您有一个相当简单的错误,主要与线程无关:
(1) func
对 stThread_t*
进行 引用 。
static int func(stThread_t *&pStThread);
(2) 您传入对 pStThread
std::thread(&CMain::func,std::ref(pStThread));
(3) 这是一个局部变量,它的生命周期在循环迭代结束后立即结束
for (int iIdx = 0; (iIdx < 5); iIdx++) {
stThread_t *pStThread = new stThread_t;
//...
}
(4) 因此,当您的函数在对象被销毁后尝试访问该对象时,您会得到未定义的行为。 (注意!这里,"the object"指的是有问题的指针,而不是指针指向的对象)
不清楚您为什么坚持通过引用传递 pStThread
;你的函数实际上并没有修改指针(只是指向什么),而且你似乎不打算做任何这样的设备实际上有好处的事情。