std::regex构造函数抛出异常



请注意,这不是StackOverflow上关于gcc的许多问题的重复,我使用的是Visual Studio 2013。

这个简单的正则表达式构造抛出std::regex_error:

bool caseInsensitive = true;
char pattern[] = "\bword\b";
std::regex re(pattern, std::regex_constants::ECMAScript | (caseInsensitive ? std::regex_constants::icase : 0));

what在异常对象上返回的实际错误不一致。通常是一个不匹配的排列或支架。为什么?

问题的出现是因为std::regex有多个构造函数可用。对构造函数的跟踪显示它使用了一个我不打算使用的构造函数!

我想用这个:

explicit basic_regex(_In_z_ const _Elem *_Ptr,
    flag_type _Flags = regex_constants::ECMAScript)

但我得到了这个:

basic_regex(_In_reads_(_Count) const _Elem *_Ptr, size_t _Count,
    flag_type _Flags = regex_constants::ECMAScript)

标志中的三元表达式导致类型更改为int,它不再与构造函数签名中的flag_type匹配。由于它size_t上进行匹配,因此它调用该构造函数。这些标志被误解为字符串的大小,导致在访问超过字符串末尾的内存时出现未定义的行为。

该问题并非Visual Studio特有。我能够在gcc中复制它:http://ideone.com/5DjYiz

它可以通过两种方式进行修复。首先是一个明确的论点:

std::regex re(pattern, static_cast<std::regex::flag_type>(std::regex_constants::ECMAScript | (caseInsensitive ? std::regex_constants::icase : 0)));

第二是避免在三元表达式中使用整数常量:

std::regex re(pattern, caseInsensitive ? std::regex_constants::ECMAScript | std::regex_constants::icase : std::regex_constants::ECMAScript);

我觉得所提出的任何一个解决方案都不是特别引人注目或美观。我想我更喜欢这样的东西:

auto options = std::regex_constants::ECMAScript;
if (caseInsensitive) 
    options |= std::regex_constants::icase;
std::regex re(pattern, options);

如果出于某种错误的原因,你真的坚持使用一行代码,我会在三元表达式中使用正确类型的值构造对象:

std::regex re(pattern, std::regex_constants::ECMAScript | (caseInsensitive ? std::regex_constants::icase : std::regex_constants::std::regex_option_type{}));

或者,由于ECMAScript是默认的,您可以使用:

std::regex re(pattern, (caseInsensitive ? std::regex_constants::icase : std::regex_constants::ECMAScript));

至少在我看来,第一个显然更可取。

最新更新