3

这是我第一次尝试使用std::future.

我要同时解析三个不同的文件。三个功能分别做到这一点。称为和。parseSentences_ 它们中的每一个都使用一个非常简单的 lambda 函数在单独的线程中启动: ,其中是一个静态变量,函数是我之前命名的三个函数之一。parseTagsparseLinksstd::async[]() { parser->function(); }parser

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 的调用堆栈在这里。线程#2 的调用堆栈在这里

请注意,this第一个调用堆栈中的指针为空,导致分段错误。

如果有人有线索,我将不胜感激。

4

2 回答 2

3

这里有一个大问题:

static parser * thisParserInstance = this;

这是在您第一次调用该函数时初始化的,然后在以后的调用中保持不变。因此,如果您在一个对象上调用该函数,销毁该对象,然后在第二个对象上调用它,您实际上将处理指向已失效对象的悬空指针。这肯定会产生未定义的行为。

没有理由使用静态变量;lambda 可以捕获this并作用于正确的对象。或者更简单地说,正如评论中所建议的,使用可变参数形式async绑定this到成员函数:

std::async(std::launch::async, &parser::parseSentences, this);
于 2012-08-27T22:17:30.563 回答
1

对不起大家。

这是解决方案:C++ 0x 的 gcc 实验实现上的 std::future 异常

与 链接后-lpthread,错误消失了。不过,感谢您的其他评论,它们非常有帮助。

于 2012-08-27T22:36:43.690 回答