我使用HtmlAgilityPack解析大约200,000个超文本标记语言文档。
我无法预测这些文档的内容,但是其中一个文档会导致我的应用程序因StackOverflowException而失败。该文档包含以下HTML:
<ol>
<li><li><li><li><li><li>...
</ol>像这样嵌套的<li>元素大约有10,000个。由于HtmlAgilityPack解析超文本标记语言的方式,它会导致StackOverflowException。
不幸的是,在.NET 2.0和更高版本中不能捕获StackOverflowException。
我确实想为线程的堆栈设置一个更大的大小,但是设置一个更大的堆栈大小是一个技巧:它会导致我的程序使用更多的内存(我的程序启动大约50个线程来处理HTML,所以所有这些线程都会增加堆栈大小),并且如果它再次遇到类似的情况,将需要手动调整。
有没有其他我可以采用的变通办法?
发布于 2012-10-01 09:00:29
理想情况下,长期的解决方案是为HtmlAgilityPack打补丁,使其使用堆栈而不是调用栈,但这对我来说太大了。我暂时丢失了我的CodePlex帐户详细信息,但当我找回它们时,我会就这个问题提交一份问题报告。我还注意到,这个问题可能会给任何使用HtmlAgilityPack清理用户提交的超文本标记语言的站点带来拒绝服务攻击漏洞--精心编制的过度嵌套的超文本标记语言文档将导致w3wp.exe进程死亡。
同时,我认为最好的方法是手动覆盖最大线程堆栈大小。我在前面的声明中错误地认为,更大的堆栈大小意味着所有线程都会自动消耗该内存(似乎内存页是随着线程堆栈的增长而分配的,而不是一次分配给所有线程堆栈)。
我复制了<ol><li>页面并运行了一些实验。我发现我的程序在堆栈大小小于2^21字节的时候失败了,但是2^22的最大大小成功了--也就是4MB,在我的书中被认为是一个“可接受的”黑客……就目前而言。
发布于 2013-03-09 04:55:19
我刚刚修补了一个错误,我相信这和你的描述是一样的。已将补丁上传到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 has more more X not。这很可能是因为页面没有正确结束标记。“
打完补丁后如何使用...
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);
}发布于 2022-01-11 10:31:59
这应该是可行的:
HtmlDocument.MaxDepthLevel = 10000;
var doc = new HtmlDocument();
try
{
doc.LoadHtml(document);
}
catch(Exception ex)
{
Console.WriteLine("Exception while loading html: " + ex);
yield break;
}https://stackoverflow.com/questions/12666282
复制相似问题