为什么 std::regex_iterator 会导致此数据的堆栈溢出
Why does std::regex_iterator cause a stack overflow with this data?
我一直在使用std::regex_iterator
来解析日志文件。 我的程序已经运行了几个星期,并且已经解析了数百万个日志行,直到今天,今天我针对日志文件运行它并出现堆栈溢出。 事实证明,日志文件中只有一个日志行导致了问题。 有谁知道为什么我的正则表达式会导致如此大规模的递归? 这是一个小型的独立程序,它显示了问题(我的编译器是VC2012):
#include <string>
#include <regex>
#include <iostream>
using namespace std;
std::wstring test = L"L3 T15356 79726859 [CreateRegistryAction] Creating REGISTRY Action:n"
L" Identity: 272A4FE2-A7EE-49B7-ABAF-7C57BEA0E081n"
L" Description: Set Registry Value: "SortOrder" in Key HKEY_CURRENT_USER\Software\Hummingbird\PowerDOCS\Core\Plugins\Fusion\Settings\DetailColumns\LONEDOCS1\Search Unsaved\$AUTHOR.FULL_NAME;DOCSADM.PEOPLE.SYSTEM_IDn"
L" Operation: 3n"
L" Hive: HKEY_CURRENT_USERn"
L" Key: Software\Hummingbird\PowerDOCS\Core\Plugins\Fusion\Settings\DetailColumns\LONEDOCS1\Search Unsaved\$AUTHOR.FULL_NAME;DOCSADM.PEOPLE.SYSTEM_IDn"
L" ValueName: SortOrdern"
L" ValueType: REG_DWORDn"
L" ValueData: 0n"
L"L4 T15356 79726859 [CEMRegistryValueAction::ClearRevertData] [ENTER]n";
int wmain(int argc, wchar_t* argv[])
{
static wregex rgx_log_lines(
L"^L(\d+)\s+" // Level
L"T(\d+)\s+" // TID
L"(\d+)\s+" // Timestamp
L"\[((?:\w|\:)+)\]" // Function name
L"((?:" // Complex pattern
L"(?!" // Stop matching when...
L"^L\d" // New log statement at the beginning of a line
L")"
L"[^]" // Matching all until then
L")*)" //
);
try
{
for (std::wsregex_iterator it(test.begin(), test.end(), rgx_log_lines), end; it != end; ++it)
{
wcout << (*it)[1] << endl;
wcout << (*it)[2] << endl;
wcout << (*it)[3] << endl;
wcout << (*it)[4] << endl;
wcout << (*it)[5] << endl;
}
}
catch (std::exception& e)
{
cout << e.what() << endl;
}
return 0;
}
在每个
角色上测试的负面展望模式对我来说似乎是一个坏主意,而且您要做的事情并不复杂。你想要匹配 (1) 行的其余部分,然后 (2) 任意数量的以下 (3) 行,这些行以 L\d 以外的内容开头(小错误;见下文):(另一个编辑:这些是正则表达式;如果你想将它们写成字符串文字,你需要更改为
\
。
.*n(?:(?:[^L]|LD).*n)*
| | |
+-1 | +---------------3
+---------------------2
在 Ecmascript 模式下,.
不应匹配 ,但您始终可以将该表达式中的两个.
替换为 [^n]
编辑以添加:我意识到如果在日志条目结束之前有一个空行,这可能不起作用,但这应该涵盖这种情况;为了提高精度,我将.
更改为[^n]
:
[^n]*n(?:(?:(?:[^Ln]|LD)[^n]*)?n)*
正则表达式似乎没问题;至少其中没有任何可能导致灾难性回溯的内容。
我看到了优化正则表达式的小可能性,减少了堆栈的使用:
static wregex rgx_log_lines(
L"^L(\d+)\s+" // Level
L"T(\d+)\s+" // TID
L"(\d+)\s+" // Timestamp
L"\[([\w:]+)\]" // Function name
L"((?:" // Complex pattern
L"(?!" // Stop matching when...
L"^L\d" // New log statement at the beginning of a line
L")"
L"[^]" // Matching all until then
L")*)" //
);
你是否设置了 ECMAScript 选项?否则,我怀疑正则表达式库默认为 POSIX 正则表达式,并且这些不支持前瞻断言。
相关文章:
- 拥有映射的现代方法,该映射可以指向或引用已在堆栈上分配的不同类型的数据
- 使用带有链表的堆栈数据结构将中缀转换为后缀
- C++,在对象内分配多个数据时,堆栈分配是否更有效? 在下面的程序中,类A_Heap的效率会更低吗?
- 函数超过堆栈大小,请考虑将一些数据移动到堆 (C6262)
- 自定义堆栈上 std::string 数据的输出
- 是否可以检查存储在堆栈上的单词是否是回文,而C++中没有任何附加数据结构
- 递归如何使用堆栈数据结构
- 比较堆栈数据结构 c++
- 使用提升库在队列和堆栈数据结构上保存和加载数据时出错
- 堆栈(数据结构)实现
- c++:堆栈上的数据,而不初始化它
- 使用临时数据表修复内存泄漏(堆与堆栈)
- 将记录推送到数据结构中的堆栈
- 尝试修改 Hbitmap 数据时出现堆栈错误
- 对私有数据进行类 - 在堆栈或堆上
- 如何拥有一个具有多个数据类型的C++堆栈
- 我需要一个像堆栈一样的数据结构,但具有随机访问,但是,我应该实现什么
- 在堆栈C++上创建的对象中存在无效数据
- 模板堆栈类:堆栈中没有显示数据
- 如何用堆栈数据结构替换递归功能调用