Umgehung einer StackOverflowException

html-agility-pack stack-overflow

Frage

Ich verwende HtmlAgilityPack, um ungefähr 200.000 HTML-Dokumente zu analysieren.

Ich kann den Inhalt dieser Dokumente nicht vorhersagen, jedoch führt ein solches Dokument dazu, dass meine Anwendung mit einer StackOverflowException fehlschlägt. Das Dokument enthält diesen HTML-Code:

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

Es gibt ungefähr 10.000 <li> -Elemente, die so verschachtelt sind. Aufgrund der Art, wie HtmlAgilityPack HTML analysiert, verursacht es eine StackOverflowException .

Leider ist eine StackOverflowException in .NET 2.0 und höher nicht abfragbar.

Ich habe mich überlegt, eine größere Größe für den Stack des Threads zu setzen, aber eine größere Stackgröße einzustellen, ist ein Hack: Es würde dazu führen, dass mein Programm viel mehr Speicher verbraucht (mein Programm startet etwa 50 Threads für die Verarbeitung von HTML, also all diese Threads) hätte die erhöhte Stack-Größe) und müsste manuell angepasst werden, falls es jemals wieder zu einer ähnlichen Situation kommen sollte.

Gibt es noch andere Problemumgehungen, die ich anwenden könnte?

Akzeptierte Antwort

Idealerweise besteht die langfristige Lösung darin, HtmlAgilityPack so zu patchen, dass ein Heap-Stack anstelle des Call-Stacks verwendet wird, aber das wäre ein zu großes Unterfangen für mich. Ich habe meine CodePlex-Kontodaten vorübergehend verloren, aber wenn ich sie zurückbekomme, werde ich einen Problembericht über das Problem einreichen. Ich stelle außerdem fest, dass dieses Problem eine Denial-of-Service-Angriffsanfälligkeit für alle Websites darstellen kann, die HtmlAgilityPack verwenden, um von Benutzern gesendete HTML-Inhalte zu bereinigen - ein manipuliertes übermäßig verschachteltes HTML-Dokument würde den w3wp.exe-Prozess zum Erliegen bringen.

In der Zwischenzeit habe ich herausgefunden, dass es am besten ist, die maximale Thread-Stack-Größe manuell zu überschreiben. Ich lag falsch in meiner früheren Aussage, dass eine größere Stack-Größe bedeutet, dass alle Threads diesen Speicher automatisch verbrauchen (es scheint, Speicherseiten werden für einen Thread-Stack zugeordnet, wenn er wächst, nicht alle auf einmal).

Ich habe eine Kopie der <ol><li> Seite erstellt und einige Experimente durchgeführt. Ich fand, dass mein Programm fehlschlug, wenn die Stack-Größe weniger als 2^21 Bytes groß war, aber eine maximale Größe von 2^22 erfolgreich - das sind 4 MB und in meinem Buch wird als "akzeptabler" Hack übergeben ... vorerst.


Beliebte Antwort

Ich habe gerade einen Fehler gepatcht, der meiner Meinung nach derselbe ist wie deine Beschreibung. Uploaded den Patch auf die Projektseite ...

http://www.codeplex.com/site/users/view/sjdirect (siehe den Patch am 08.03.2012)

Oder sehen Sie mehr Dokumentation des Problems und Ergebnis hier ....

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

Das eigentliche Update wurde ... HtmlDocument.OptionMaxNestedChildNodes hinzugefügt, die festgelegt werden können, um StackOverflowExceptions zu verhindern, die durch viele verschachtelte Tags verursacht werden. Es wird eine ApplicationException mit der Nachricht "Dokument enthält mehr als X verschachtelte Tags" ausgelöst. Dies liegt wahrscheinlich daran, dass die Seite die Tags nicht korrekt schließt. "

Wie ich Hap nach Patch verwende ...

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



Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum