Html Agility Pack 라이브러리 Stack Overflow Exception 솔루션

2799 단어 exception
최근에 Html Agility Pack을 사용해서 html을 해석했습니다. 시험 과정에서 프로그램은 Stack Overflow Exception 이상을 던져서 MSDN에서 볼 수 있습니다.NET Framework 2.0 버전이 시작되면try-catch 블록을 통해 Stack Overflow Exception 객체를 캡처할 수 없으며 기본적으로 프로세스가 종료됩니다.
 
조사 원인, 한 html 구조가 매우 복잡할 때 Html Agility Pack의 귀환 횟수가 매우 많은 것을 발견하여 Stack Overflow Exception 이상에 대해 보고했고 구글은 아래솔루션를 찾아냈다.
먼저 라이브러리에 클래스를 추가합니다.
public class StackChecker

{

    public unsafe static bool HasSufficientStack(long bytes)

    {

        var stackInfo = new MEMORY_BASIC_INFORMATION();



        // We subtract one page for our request. VirtualQuery rounds UP to the next page.

        // Unfortunately, the stack grows down. If we're on the first page (last page in the

        // VirtualAlloc), we'll be moved to the next page, which is off the stack! Note this

        // doesn't work right for IA64 due to bigger pages.

        IntPtr currentAddr = new IntPtr((uint)&stackInfo - 4096);



        // Query for the current stack allocation information.

        VirtualQuery(currentAddr, ref stackInfo, sizeof(MEMORY_BASIC_INFORMATION));



        // If the current address minus the base (remember: the stack grows downward in the

        // address space) is greater than the number of bytes requested plus the reserved

        // space at the end, the request has succeeded.

        return ((uint)currentAddr.ToInt64() - stackInfo.AllocationBase) >

            (bytes + STACK_RESERVED_SPACE);

    }



    // We are conservative here. We assume that the platform needs a whole 16 pages to

    // respond to stack overflow (using an x86/x64 page-size, not IA64). That's 64KB,

    // which means that for very small stacks (e.g. 128KB) we'll fail a lot of stack checks

    // incorrectly.

    private const long STACK_RESERVED_SPACE = 4096 * 16;



    [DllImport("kernel32.dll")]

    private static extern int VirtualQuery(

        IntPtr lpAddress,

        ref MEMORY_BASIC_INFORMATION lpBuffer,

        int dwLength);



    private struct MEMORY_BASIC_INFORMATION

    {

        internal uint BaseAddress;

        internal uint AllocationBase;

        internal uint AllocationProtect;

        internal uint RegionSize;

        internal uint State;

        internal uint Protect;

        internal uint Type;

    }

}

 
그리고 귀환 횟수가 많은 곳(such as Html Node. Write To(Text Writer out Text) and Html Node.WriteTo(XmlWriter writer):) 다음 코드를 추가합니다.
if (!StackChecker.HasSufficientStack(4*1024))

                throw new Exception("The document is too complex to parse");

 
오케이, 큰일 났다!

좋은 웹페이지 즐겨찾기