1

C#からHtmlTidyライブラリdllを呼び出そうとしています。ネット上に浮かんでいるいくつかの例がありますが、決定的なものは何もありません...そして私は問題の終わりがありません。問題はp/invoke宣言にあると確信しています...しかし、どこが間違っているのかがわかっている場合は、問題が発生します。

libtidy.dllをhttp://www.paehl.com/open_source/?HTML_Tidy_for_Windowsから入手しました。これは現在のバージョンのようです。

これが私が抱えている問題を示すコンソールアプリです:

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace ConsoleApplication5
{
    class Program
    {
        [StructLayout(LayoutKind.Sequential)]
        public struct TidyBuffer
        {
            public IntPtr bp;         // Pointer to bytes
            public uint size;         // # bytes currently in use
            public uint allocated;    // # bytes allocated
            public uint next;         // Offset of current input position
        };

        [DllImport("libtidy.dll")]
        public static extern int tidyBufAlloc(ref TidyBuffer tidyBuffer, uint allocSize);


        static void Main(string[] args)
        {
            Console.WriteLine(CleanHtml("<html><body><p>Hello World!</p></body></html>"));
        }

        static string CleanHtml(string inputHtml)
        {
            byte[] inputArray = Encoding.UTF8.GetBytes(inputHtml);
            byte[] inputArray2 = Encoding.UTF8.GetBytes(inputHtml);

            TidyBuffer tidyBuffer2;
            tidyBuffer2.size = 0;
            tidyBuffer2.allocated = 0;
            tidyBuffer2.next = 0;
            tidyBuffer2.bp = IntPtr.Zero;

            //
            // tidyBufAlloc overwrites inputArray2... why? how? seems like
            // tidyBufAlloc is stomping on the stack a bit too much... but
            // how? I've tried changing the calling convention to cdecl and
            // stdcall but no change.
            //
            Console.WriteLine((inputArray2 == null ? "Array2 null" : "Array2 not null"));
            tidyBufAlloc(ref tidyBuffer2, 65535);
            Console.WriteLine((inputArray2 == null ? "Array2 null" : "Array2 not null"));
            return "did nothing";
        }
    }
}

全体として、私は少し困惑しています。どんな助けでもいただければ幸いです!

4

3 に答える 3

3

TidyBuffer構造の古い定義を使用しています。新しい構造はより大きくなるため、allocateメソッドを呼び出すと、inputArray2のスタック位置が上書きされます。新しい定義は次のとおりです。

    [StructLayout(LayoutKind.Sequential)]        
    public struct TidyBuffer        
    {
        public IntPtr allocator;  // Pointer to custom allocator            
        public IntPtr bp;         // Pointer to bytes            
        public uint size;         // # bytes currently in use            
        public uint allocated;    // # bytes allocated            
        public uint next;         // Offset of current input position        
    };        
于 2009-05-17T12:46:31.860 に答える
2

その価値については、職場でTidyを試し、HtmlAgilityPackに切り替えました。

于 2009-05-09T05:44:16.933 に答える
0

tidyBufAlloc宣言を次のように変更してみてください。

[DllImport("libtidy.dll", CharSet = CharSet.Ansi)]
private static extern int tidyBufAlloc(ref TidyBuffer Buffer, int allocSize);

CharSet.Ansiの追加と「intallocSize」(uintの代わりに)に注意してください。

また、C#でHTML Tidyを使用する例については、このサンプルコードを参照してください。

あなたの例では、inputHTMLが大きい場合、たとえば50Kの場合、inputArrayとinputArray2もそれぞれ50Kになります。

次に、tidyBufAlloc呼び出しで65Kを割り当てようとしています。

ポインタが正しく初期化されていない場合は、ランダムな.NETヒープアドレスが使用されている可能性があります。したがって、一見無関係に見える変数/バッファの一部またはすべてが上書きされます。運が良ければ、またはすでに大きなバッファを割り当てているので、無効なメモリアクセスエラーが発生する可能性のあるコードブロックを上書きしていない可能性があります。

于 2009-05-09T04:58:06.497 に答える