2012-10-01 17 views
5

私はHtmlAgilityPackを使用して、約200,000のHTMLドキュメントを解析しています。回避策StackOverflowException

私はこれらのドキュメントの内容を予測することはできませんが、そのようなドキュメントの1つはStackOverflowExceptionで失敗することになります。文書では、このHTMLが含まれています

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

そのように入れ子におよそ万<li>の要素があります。 HtmlAgilityPackがHTMLを解析する方法のために、StackOverflowExceptionが発生します。

残念ながら、StackOverflowExceptionは.NET 2.0以降ではキャッチできません。

私は、スレッドのスタックのサイズを大きく設定することに戸惑いましたが、大きなスタックサイズを設定するとハッキングになります。プログラムによって多くのメモリが使用されます(私のプログラムはHTML処理に約50スレッドを開始します。これらのスレッドはすべてスタックサイズが大きくなります)、同様の状況が発生した場合は手動で調整する必要があります。

他にも採用できる回避策はありますか?

+0

ありません。別のライブラリに切り替える気がしない限り、スタックサイズを増やすよりも良い方法はありません。おそらく、それを必要とするスレッドのためだけにスタックサイズを設定する方法がありますか? –

答えて

2

長期的な解決策は、HtmlAgilityPackにコールスタックの代わりにヒープスタックを使用するようにパッチを適用することですが、それは私には大きすぎます。私は一時的に私のCodePlexアカウントの詳細を失ってしまいました。しかし、私がそれらを取り戻すと、私は問題に関する問題レポートを提出します。また、この問題により、HtmlAgilityPackを使用してユーザーが送信したHTMLをサニタイズするサイトにDoS攻撃の脆弱性が存在する可能性があることにも注意してください。

それまでの最善の方法は、最大スレッドスタックサイズを手動でオーバーライドすることです。以前のステートメントでは、スタックサイズが大きいということは、すべてのスレッドが自動的にそのメモリを消費することを意味していました(メモリページはスレッドスタックに割り当てられているように見えます。

私は<ol><li>ページのコピーを作成し、いくつかの実験を行いました。スタックサイズが2^21バイト未満で最大サイズが2^22に達したときにプログラムが失敗したことが判明しました。これは4MBで、私の本では「受け入れ可能な」ハックとして渡されています。

5

あなたの記述と同じと思われるエラーを修正したばかりです。

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

(2012年3月8日にパッチを参照)... HAPのプロジェクトサイトに

http://www.codeplex.com/site/users/view/sjdirectをパッチをアップロードまたは問題のより多くのドキュメントを参照してください、ここで結果

実際の修正はした...ネストされたタグのトンによって引き起こされるStackOverflowExceptionsを防ぐために設定することができます を追加しましたHtmlDocument.OptionMaxNestedChildNodes。これは、 "ドキュメントにX個以上のネストされたタグがあります。これは、タグを適切に閉じていないページが原因です。"というメッセージとともにApplicationExceptionをスローします。私はパッチ後ハップを使用していますどのように

...本当に

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