StackOverflowExceptionを回避する

html-agility-pack stack-overflow

質問

私はHtmlAgilityPackを使って約200,000のHTML文書を解析しています。

私はこれらのドキュメントの内容を予測することはできませんが、そのようなドキュメントの1つが私のアプリケーションをStackOverflowException失敗させる原因になります。ドキュメントには次のHTMLが含まれています:

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

大体万があります<li>そのようにネストされた要素が。 HtmlAgilityPackがHTMLを解析するため、 StackOverflowException発生します。

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

私はスレッドのスタックのために大きなサイズを設定するのには不思議でしたが、より大きなスタックサイズを設定することはハックです:それは私のプログラムがもっと多くのメモリを使用するようになります(私のプログラムはHTMLを処理するために約50スレッドを開始するので、スタックサイズが大きくなります)、同様の状況に再び遭遇した場合は手動で調整する必要があります。

他の回避策がありますか?

受け入れられた回答

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

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

私は<ol><li>ページのコピーを作り、いくつかの実験を行った。スタックサイズが2^21バイト未満で、 2^22最大サイズが成功しました。これは4MBで、私の本では "受け入れ可能な"ハックとして渡されています。


人気のある回答

私はちょうどあなたの記述と同じであると信じているエラーを修正しました。ハッププロジェクトサイトにパッチをアップロードしました...

http://www.codeplex.com/site/users/view/sjdirect(2012年3月8日のパッチを参照)

または、問題と結果の詳細なドキュメントを参照してください....

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

実際の修正は... HtmlDocument.OptionMaxNestedChildNodesが追加され、多数のネストされたタグによって引き起こされるStackOverflowExceptionsを防ぐことができます。これは、 "ドキュメントに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);
}


Related

ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow