为什么不同的 GCC 4.9.2 安装为此正则表达式匹配给出不同的结果



我在ideone和Coliru上发布了以下代码:

#include <iostream>
#include <regex>
#include <string>
int main() 
{
    std::string example{"   <match1>  <match2>    <match3>"};
    std::regex re{"<([^>]+)>"};
    std::regex_token_iterator<std::string::iterator> it{example.begin(), example.end(), re, 1};
    decltype(it) end{};
    while (it != end) std::cout << *it++ << std::endl;
    return 0;
}

两个站点都使用 GCC 4.9.2。我不知道 ideone 使用什么编译参数,但在 Coliru 中没有什么不寻常的。

Coliru 没有给我match1结果:

科里鲁

# g++ -v 2>&1 | grep version; 
# g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
gcc version 4.9.2 (GCC) 
match2
match3

ideone(顺便说一下,Coliru的clang 3.5.0使用libc++)

match1
match2
match3

我的代码是否有未定义的行为或其他东西?什么原因可能导致这种情况?

这是

libstdc++的regex_token_iterator复制构造函数中的一个错误,由postincrement运算符调用。 该错误已于 2014 年 12 月修复;此后发布的 GCC 4.9 和 5.x 版本将具有修复程序。该 bug 的本质是迭代器的副本为副本的目标提供别名,从而导致观察到的行为。

解决方法是使用预增量 - 从微优化的角度来看,这也是可取的,因为regex_token_iterator是一个相当重的类:

for (; it != end; ++it) std::cout << *it << std::endl;

代码有效。

唯一合理的解释是标准库版本不同;尽管在大多数情况下,标准库实现都随编译器一起提供,但它们可以通过Linux包管理器进行独立升级。

在这种情况下,这似乎是去年年底修复的libstdc++错误:

  • 科里鲁有__GLIBCXX__ == 20141030
  • Ideone有__GLIBCXX__ == 20141220

我能找到的 Bugzilla 上最有可能的匹配项是 bug 63497,但老实说,我不相信这个特定的错误曾经被 Bugzilla 完全覆盖过。约瑟夫·曼斯菲尔德(Joseph Mansfield)发现,在这种特定情况下,这些特定症状至少是由修复后增量触发的。

最新更新