这是我第一次尝试使用 std::future
。
我想同时解析三个不同的文件。三个功能分别做到了这一点。称为 parseSentences
、parseTags
和 parseLinks
。它们中的每一个都通过一个非常简单的 lambda 函数使用 std::async
在单独的线程中启动:[]() { parser->function(); }
,其中 parser
是一个静态变量,function 是我之前命名的三个函数之一。
int parser::start()
{
int ret = SUCCESS;
ASSERT( m_output != nullptr );
static parser * thisParserInstance = this;
// parsing files
std::future<int> parseSentence = std::async(std::launch::async, []() { return thisParserInstance->parseSentences(); } );
std::future<int> parseLinksResult = std::async(std::launch::async, []() { return thisParserInstance->parseLinks(); } );
std::future<int> parseTagsResult = std::async(std::launch::async, []() { return thisParserInstance->parseTags(); } );
// retrieving the results
ret = parseSentence.get();
const int linksResult = parseLinksResult.get();
const int tagsResult = parseTagsResult.get();
if (ret == SUCCESS)
ret = linksResult == SUCCESS ? tagsResult : linksResult;
return ret;
}
现在,当我在 gdb 中运行我的程序时,在破坏 std::future
局部变量之一时发生段错误。当时有 2 个线程在运行。
线程 #1 的调用栈是 here .
线程 #2 的调用栈是 here .
请注意,第一个调用堆栈中指向this
的指针为空,从而导致段错误。
如果有人知道,我将不胜感激。
最佳答案
这里有一个大问题:
static parser * thisParserInstance = this;
这是在您第一次调用该函数时初始化的,然后在以后的调用中保持不变。因此,如果您在一个对象上调用该函数,销毁该对象,然后在第二个对象上调用它,您实际上是在处理一个指向已失效对象的悬空指针。这肯定会产生未定义的行为。
没有理由使用静态变量; lambda 可以捕获 this
并作用于正确的对象。或者更简单地说,如评论中所建议的那样,使用可变形式的 async
将 this
绑定(bind)到成员函数:
std::async(std::launch::async, &parser::parseSentences, this);
关于c++ - 为什么这段代码会产生竞争条件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12150342/