Visual Studio regex_iterator Bug?

时间:2015-04-27 12:26:43

标签: c++ regex c++11 visual-studio-2013 assertion

我在Visual Studio 2013上,我看到了我认为的错误,我希望有人可以确认?

string foo{ "A\nB\rC\n\r" };
vector<string> bar;

for (sregex_iterator i(foo.cbegin(), foo.cend(), regex("(.*)[\n\r]{1,2}")); i != sregex_iterator(); ++i){
    bar.push_back(i->operator[](1).str());
}

此代码命中Visual Studio regex库中的Debug Assertion:

  

regex_iterator孤儿

如果我在regex之外定义for - 循环就可以了:

string foo{ "A\nB\rC\n\r" };
vector<string> bar;
regex bug("(.*)[\n\r]{1,2}");

for (sregex_iterator i(foo.cbegin(), foo.cend(), bug); i != sregex_iterator(); ++i){
    bar.push_back(i->operator[](1).str());
}

或者,这可以在变换中正常工作,如this question

所示
string foo{ "A\nB\rC\n\r" };
vector<string> bar;

// This puts {"A", "B", "C"} into bar
transform(sregex_iterator(foo.cbegin(), foo.cend(), regex("(.*)[\n\r]{1,2}")), sregex_iterator(), back_inserter(bar), [](const smatch& i){ return i[1].str(); });

有人可以确认这是一个错误吗?

2 个答案:

答案 0 :(得分:10)

在C ++ 11中,您可以将临时regex绑定到const regex &,如果迭代器在临时生命周期之外使用,则会导致未定义的行为,因为它将存储指针它。这是规范中的一个缺陷,虽然Visual Studio使用调试断言来捕获它,但它并不是错误。

sregex_iterator i(foo.cbegin(), foo.cend(), regex("(.*)[\n\r]{1,2}"))
                                            ^^^^^
                                            temporary

以下已删除的重载是在{+ 3}}中添加C ++ 14以防止出现这种情况:

regex_iterator(BidirIt, BidirIt,
           const regex_type&&,
           std::regex_constants::match_flag_type =
           std::regex_constants::match_default) = delete;       (since C++14)

它说:

  

不允许使用临时正则表达式调用重载2,   因为返回的迭代器会立即失效。

因此,这不是Visual Studio错误,因为它正在实施C ++ 11标准,直到后来才通过缺陷报告解决。使用clang或更高版本的gcc-std=c++14都会产生第一个错误( cppreference )和第三个错误( {{3 }} )示例。 Visual Studio仅开始支持see it live中的某些C ++ 14:

  

[...]以及对某些C ++ 14功能的初始支持。[...]

我们可以看到see it live处理此问题:

  

用户可以写“for(sregex_iterator i(s.begin(),s.end(),   正则表达式(“喵”)),结束;我!=结束; ++ i)“,将临时正则表达式绑定到   const regex&amp;并存储指向它的指针。这将静默编译,   在运行时触发未定义的行为。我们现在拥有这项技术   防止这种情况编译,就像reference_wrapper拒绝一样   绑定到临时工。

作为T.C.指出你显示的最后一个例子实际上是好的,即使你绑定了一个临时的,它的生命周期延伸到了表达式的结尾。

答案 1 :(得分:2)

不,这不是错误。见LWG 2329 regex_match()/regex_search() with match_results should forbid temporary strings。此构造表现出未定义的行为,因为它将临时正则表达式绑定到const正则表达式&amp;并存储指向它的指针。

另请参阅C++14 STL Features, Fixes, And Breaking Changes In Visual Studio 14 CTP1,其中列出了此修复程序。