我将astd::sub_match
作为参数传递给a std::thread
(请参见下面的示例代码)。线程函数需要一个const字符串引用。sub_match可以转换为字符串。所以一切都编译良好。
但是有时函数会收到错误的字符串。当我在将sub_match传递给线程之前将其转换为字符串时,它可以按预期工作。有什么不同?
我认为这是一个竞争条件,因为线程执行时原始的sub_match可能不再存在。但是我认为线程的参数还是会被复制。我如何找出哪些参数可以安全地传递给线程,哪些不可以?
#include <iostream>
#include <string>
#include <vector>
#include <thread>
#include <regex>
#include <unistd.h>
class test_t {
public:
test_t(void) {}
~test_t(void) {}
void start(void){
//-------------------------------------------------
// Do some memory allocation.
// The error seems to appear faster with that.
std::vector<std::string> vec;
for(unsigned int i = 0; i < 1000; ++i) {
vec.push_back("test_test_test");
}
//-------------------------------------------------
std::string event = "operating";
std::smatch match;
std::regex expr("\\(operating\\)",
std::regex_constants::icase |
std::regex_constants::basic);
if(std::regex_match(event, match, expr)) {
std::cout << "start thread" << std::endl;
m_thread = std::thread(&test_t::thread_func, this, match[1]); //NOK
// m_thread = std::thread(&test_t::thread_func, this, match[1].str()); // OK
// m_thread = std::thread(&test_t::thread_func, this, (std::string)match[1]); // OK
m_thread.detach();
std::cout << "thread started" << std::endl;
}
}
private:
std::thread m_thread;
void thread_func(const std::string& string) {
if(string != "operating") {
std::cout << "ERROR: string: \"" << string << "\"" << std::endl;
exit(EXIT_FAILURE);
} else {
std::cout << "string: \"" << string << "\"" << std::endl;
}
}
};
int main(int argc, char** argv) {
test_t test;
while(1) {
test.start();
usleep(100);
}
return 0;
}
编译消息:
Compiled with: g++ --std=c++11 -pthread -o test main.cpp
g++ --version: g++ (SUSE Linux) 4.8.5
预期产量:
start thread
thread started
string: "operating"
(repeat)
实际输出:
start thread
thread started
string: "operating"
ERROR: string: "test_test"
operator[]
对于可以视为匹配字符的迭代器对的std::smatch
返回sub_match
。
之后regex_match
被调用,您可以使用operator[]
,只要访问子匹配event
存在。当event
被删除时(您没有加入线程,因此会start
立即返回并被event
销毁),子匹配项具有悬空的指针,不应访问。
m_thread = std::thread(&test_t::thread_func, this, match[1]);
这是行不通的,因为当函数超出范围时,事件将被删除并且子匹配项具有悬空的指针。
m_thread = std::thread(&test_t::thread_func, this, match[1].str());
之所以有效,是因为str()
返回匹配字符串的副本。
m_thread = std::thread(&test_t::thread_func, this, (std::string)match[1]);
这也是有效的,因为根据sub-match创建了临时字符串match[1]
,并将temp传递给了线程。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句