解決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);
}



許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因