2012-10-01 184 views
5

我使用HtmlAgilityPack來解析大約200,000個HTML文檔。解決方法StackOverflowException

我無法預測這些文檔的內容,但是一個這樣的文檔導致我的應用程序失敗,出現StackOverflowException。該文檔包含以下HTML:

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

大致有10,000個<li>這樣的嵌套元素。由於HtmlAgilityPack解析HTML的方式,導致StackOverflowException

不幸的是,StackOverflowException在.NET 2.0及更高版本中不可捕捉。我想知道爲線程的堆棧設置一個更大的大小,但是設置一個更大的堆棧大小是一個駭客:它會導致我的程序使用更多的內存(我的程序啓動大約50個線程來處理HTML,所以所有這些線程都會增加堆棧大小),並且如果它再次遇到類似情況,則需要手動調整。

有沒有其他解決方法可以使用?

+0

不是真的。除非您想切換到不同的庫,否則我看不到增加堆棧大小的更好方法。也許有一種方法只爲需要的線程設置堆棧大小? –

回答

2

理想情況下,長期的解決方案是修補HtmlAgilityPack以使用堆棧而不是調用堆棧,但這對我來說太大了。我暫時失去了我的CodePlex帳戶詳細信息,但是當我將它們還給他人時,我會提交問題報告。我還注意到,這個問題可能會給任何使用HtmlAgilityPack來清理用戶提交的HTML的站點帶來拒絕服務攻擊漏洞 - 一個精心製作的嵌套HTML文檔會導致w3wp.exe進程死亡。

與此同時,我認爲最好的方法是手動覆蓋最大線程堆棧大小。我在之前的聲明中錯誤地認爲,更大的堆棧大小意味着所有線程都會自動消耗該內存(看起來內存頁面隨着它增長而分配給線程堆棧,而不是一次全部分配)。

我製作了<ol><li>頁面的副本並進行了一些實驗。當堆棧大小小於2^21字節時,我發現程序失敗,但最大大小爲2^22成功 - 這是4MB,並且在我的書中作爲「可接受的」黑客入侵......現在。

5

我只是修補了一個錯誤,我相信這與您的描述相同。上傳補丁到HAP項目現場......

http://www.codeplex.com/site/users/view/sjdirect(見2012/3/8補丁)

還是看到了問題的更多的文檔,並導致這裏....

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

實際修復是......可以設置以防止由噸嵌套標籤造成StackOverflowExceptions 新增HtmlDocument.OptionMaxNestedChildNodes。它會拋出一個ApplicationException消息「Document有多個X嵌套標籤,這可能是由於頁面沒有正確關閉標籤。」

我如何使用廈門補丁後...

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