Visual Studio regex_iterator 错误?
Visual Studio regex_iterator Bug?
我在 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_iterator
orphaned
如果我在 for
循环外定义 regex
没问题:
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());
}
或者,这在 :
所示的转换中工作正常
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(); });
有人可以确认这是一个错误吗?
在 C++11 中,您可以将临时 regex
绑定到 const regex &
,如果迭代器在临时生命周期之外使用,这可能会导致未定义的行为,因为它将存储指向它的指针。这是规范中的一个缺陷,不是错误,尽管 Visual Studio 使用调试断言捕获了它。
sregex_iterator i(foo.cbegin(), foo.cend(), regex("(.*)[\n\r]{1,2}"))
^^^^^
temporary
在 C++14 中添加了以下删除的重载以防止这种情况,来自 cppreference:
regex_iterator(BidirIt, BidirIt,
const regex_type&&,
std::regex_constants::match_flag_type =
std::regex_constants::match_default) = delete; (since C++14)
它说:
The overload 2 is not allowed to be called with a temporary regex,
since the returned iterator would be immediately invalidated.
所以这不是 Visual Studio
错误,因为它正在实现 C++11 标准,并且直到后来才通过缺陷报告解决这个问题。使用 -std=c++14
或更高版本的 clang
和 gcc
都会在您的第一个 (see it live) and third(see it live) example. Visual Studio only started supporting some C++14 in VS 2015:
中产生错误
[...]and initial support for certain C++14 features.[...]
我们可以看到LWG defect 2332: regex_iterator/regex_token_iterator should forbid temporary regexes处理这个:
Users can write "for(sregex_iterator i(s.begin(), s.end(),
regex("meow")), end; i != end; ++i)", binding a temporary regex to
const regex& and storing a pointer to it. This will compile silently,
triggering undefined behavior at runtime. We now have the technology
to prevent this from compiling, like how reference_wrapper refuses to
bind to temporaries.
如T.C。指出你展示的最后一个例子实际上没问题,即使你绑定了一个临时的它的生命周期延伸到表达式的末尾。
不,这不是错误。参见 LWG 2329 regex_match()/regex_search() with match_results should forbid temporary strings。此构造表现出未定义的行为,因为它将临时正则表达式绑定到 const regex& 并存储指向它的指针。
另请参阅 C++14 STL Features, Fixes, And Breaking Changes In Visual Studio 14 CTP1,其中将其列为修复程序。
我在 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_iterator
orphaned
如果我在 for
循环外定义 regex
没问题:
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());
}
或者,这在
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(); });
有人可以确认这是一个错误吗?
在 C++11 中,您可以将临时 regex
绑定到 const regex &
,如果迭代器在临时生命周期之外使用,这可能会导致未定义的行为,因为它将存储指向它的指针。这是规范中的一个缺陷,不是错误,尽管 Visual Studio 使用调试断言捕获了它。
sregex_iterator i(foo.cbegin(), foo.cend(), regex("(.*)[\n\r]{1,2}"))
^^^^^
temporary
在 C++14 中添加了以下删除的重载以防止这种情况,来自 cppreference:
regex_iterator(BidirIt, BidirIt,
const regex_type&&,
std::regex_constants::match_flag_type =
std::regex_constants::match_default) = delete; (since C++14)
它说:
The overload 2 is not allowed to be called with a temporary regex, since the returned iterator would be immediately invalidated.
所以这不是 Visual Studio
错误,因为它正在实现 C++11 标准,并且直到后来才通过缺陷报告解决这个问题。使用 -std=c++14
或更高版本的 clang
和 gcc
都会在您的第一个 (see it live) and third(see it live) example. Visual Studio only started supporting some C++14 in VS 2015:
[...]and initial support for certain C++14 features.[...]
我们可以看到LWG defect 2332: regex_iterator/regex_token_iterator should forbid temporary regexes处理这个:
Users can write "for(sregex_iterator i(s.begin(), s.end(), regex("meow")), end; i != end; ++i)", binding a temporary regex to const regex& and storing a pointer to it. This will compile silently, triggering undefined behavior at runtime. We now have the technology to prevent this from compiling, like how reference_wrapper refuses to bind to temporaries.
如T.C。指出你展示的最后一个例子实际上没问题,即使你绑定了一个临时的它的生命周期延伸到表达式的末尾。
不,这不是错误。参见 LWG 2329 regex_match()/regex_search() with match_results should forbid temporary strings。此构造表现出未定义的行为,因为它将临时正则表达式绑定到 const regex& 并存储指向它的指针。
另请参阅 C++14 STL Features, Fixes, And Breaking Changes In Visual Studio 14 CTP1,其中将其列为修复程序。