【问题标题】:Why do different GCC 4.9.2 installations give different results for this regex match?为什么不同的 GCC 4.9.2 安装会为此正则表达式匹配给出不同的结果?
【发布时间】:2015-06-27 08:27:46
【问题描述】:

我在ideoneColiru 上发布了以下代码:

#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's clang 3.5.0 using libc++

match1
match2
match3

我的代码有未定义的行为吗?是什么原因造成的?

【问题讨论】:

  • 感谢“Veritas”在聊天中提出这个问题。
  • 一个明显的可能性:即使他们使用相同的编译器,他们使用不同的标准库。
  • GCC 通常不附带特定的 libstdc++ 版本吗?如果 libstdc++ 版本在 GCC 4.9.2 安装之间存在差异(通常),难道不会出现问题吗?
  • Hmmmm...将++ 移出*it++ 可以在Coliru 中修复它。是否存在在 regex_token_iterator 上的后修复 ++ 返回错误对象的错误?也就是说,它似乎在 增量之后返回对象。

标签: c++ regex gcc c++14


【解决方案1】:

它是a bug in libstdc++'s regex_token_iterator copy constructor,由后增量运算符调用。该错误已于 2014 年 12 月修复;此后发布的 gcc 4.9 和 5.x 版本将进行修复。该错误的本质是迭代器的副本为副本的目标起别名,从而导致观察到的行为。

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

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

【讨论】:

    【解决方案2】:

    代码有效。

    唯一合理的解释是标准库版本不同;尽管大部分标准库实现都附带编译器,但它们可以通过例如 Linux 包管理器独立升级。

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

    我能在 Bugzilla 上找到的最有可能的匹配项是 bug 63497,但老实说,我不相信 Bugzilla 曾经完全覆盖过这个特定的错误。 Joseph Mansfieldidentifiedthese specific symptoms in this specific case are triggered by the post-fix increment,至少。

    【讨论】:

    • 这是正在实施的originoperator++,它似乎是正确的。这告诉我这可能是复制构造函数的错误(也许?)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-04
    • 2012-11-14
    • 1970-01-01
    • 2012-06-09
    • 1970-01-01
    相关资源
    最近更新 更多