解决StackOverflowException问题

html-agility-pack stack-overflow

我正在使用HtmlAgilityPack来解析大约200,000个HTML文档。

我无法预测这些文档的内容,但是一个这样的文档会导致我的应用程序因StackOverflowException而失败。该文档包含此HTML:

<ol>
    <li><li><li><li><li><li>...
</ol>

大约有10,000个<li>元素嵌套在那里。由于HtmlAgilityPack解析HTML的方式导致StackOverflowException

不幸的是,在.NET 2.0及更高版本中无法捕获StackOverflowException。

我确实想知道为线程的堆栈设置更大的大小,但设置更大的堆栈大小是一个黑客:它会导致我的程序使用更多的内存(我的程序启动大约50个线程来处理HTML,所以所有这些线程将有更大的堆栈大小)并将需要手动调整,如果它再次遇到类似的情况。

我可以使用其他解决方法吗?

一般承认的答案

理想情况下,长期解决方案是修补HtmlAgilityPack使用堆栈而不是调用堆栈,但这对我来说太大了。我暂时丢失了我的CodePlex帐户详细信息,但当我收回它时,我会提交一份有关问题的问题报告。我还注意到,此问题可能会对使用HtmlAgilityPack清理用户提交的HTML的任何站点提出拒绝服务攻击漏洞 - 精心设计的过度嵌套的HTML文档会导致w3wp.exe进程死亡。

与此同时,我认为最好的方法是手动覆盖最大线程堆栈大小。我之前的陈述中错误的是,更大的堆栈大小意味着所有线程都自动消耗该内存(似乎内存页面在增长时为线程堆栈分配,而不是一次性分配)。

我复制了<ol><li>页面并进行了一些实验。我发现我的程序在堆栈大小小于2^21字节大小时失败了,但是最大大小为2^22成功 - 这是4MB并且在我的书中传递为“可接受的”黑客......现在。


热门答案

我刚刚修补了一个错误,我认为该错误与您的描述相同。上传补丁到hap项目网站......

http://www.codeplex.com/site/users/view/sjdirect (参见2012年3月8日的补丁)

或者在这里查看有关问题和结果的更多文档....

https://code.google.com/p/abot/issues/detail?id=77

实际修复是...添加了HtmlDocument.OptionMaxNestedChildNodes,可以设置为防止由大量嵌套标记引起的StackOverflowExceptions。它将抛出一个ApplicationException,消息“Document包含多个X嵌套标记。这可能是因为页面没有正确关闭标记。”

我如何在补丁后使用Hap ...

HtmlDocument hapDoc = new HtmlDocument();
hapDoc.OptionMaxNestedChildNodes = 5000;//This is what was added
string rawContent = GETTHECONTENTHERE
try
{
    hapDoc.LoadHtml(RawContent);    
}
catch (Exception e)
{
    //Instead of a stackoverflow exception you should end up here now
    hapDoc.LoadHtml("");
    _logger.Error(e);
}


Related

许可下: CC-BY-SA with attribution
不隶属于 Stack Overflow
许可下: CC-BY-SA with attribution
不隶属于 Stack Overflow