解决StackOverflowException问题

Dai*_*Dai 5 stack-overflow html-agility-pack

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

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

<ol>
    <li><li><li><li><li><li>...
</ol>
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

sjd*_*ect 5

我刚刚修补了一个错误,我认为该错误与您的描述相同.上传补丁到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);
}
Run Code Online (Sandbox Code Playgroud)


Dai*_*Dai 2

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

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

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