-1

ネイティブのC#の代替手段は遅いため、kernel32のReadFileを機能させようとしています...

次のコードは数回機能していましたが、突然「保護されたメモリの読み取りまたは書き込みを試みました。これは、多くの場合、他のメモリが破損していることを示しています。」

サーバーを再起動すると、同じエラーが発生する前に数回機能すると思いましたが、間違っていたようです。今何をしても発生します..

これが私のコードです:

using System.Runtime.InteropServices;



private WinFileIO.WinFileIO _winFile;

_winFile = new WinFileIO.WinFileIO(new byte[bufferSize]);
_winFile.OpenForReading(_fileInfo.FullName);


public WinFileIO(Array Buffer)
{
    PinBuffer(Buffer);
    pHandleRead = IntPtr.Zero;
    pHandleWrite = IntPtr.Zero;
    bufferSize = Buffer.GetLength(0);
}


private void PinBuffer(Array Buffer)
{
    UnpinBuffer();
    gchBuf = GCHandle.Alloc(Buffer, GCHandleType.Pinned);
    IntPtr pAddr = Marshal.UnsafeAddrOfPinnedArrayElement(Buffer, 0);
    // pBuffer is the pointer used for all of the I/O functions in this class.
    pBuffer = (void*)pAddr.ToPointer();
}


public void UnpinBuffer()
{
    if (gchBuf.IsAllocated)
        gchBuf.Free();
}


[System.Runtime.InteropServices.DllImport("kernel32", SetLastError = true)]
static extern unsafe System.IntPtr CreateFile
(
     string FileName,          // file name
     uint DesiredAccess,       // access mode
     uint ShareMode,           // share mode
     uint SecurityAttributes,  // Security Attributes
     uint CreationDisposition, // how to create
     uint FlagsAndAttributes,  // file attributes
     int hTemplateFile         // handle to template file
);


[System.Runtime.InteropServices.DllImport("kernel32", SetLastError = true)]
private unsafe static extern bool ReadFile
(
    int hFile, 
    byte[] arraypBuffer,
    int NumberOfBytesToRead,
    ref int lpNumberOfBytesToRead,
    int* ptr
);


[System.Runtime.InteropServices.DllImport("kernel32", SetLastError = true)]
static extern unsafe bool SetFilePointer
(
    System.IntPtr hObject,
    int lDistanceToMove,
    ref int lpDistanceToMoveHigh,
    EMoveMethod dwMoveMethod
);


public void OpenForReading(string FileName)
{
    Close(true, false);
    pHandleRead = CreateFile(FileName, 3, 3, 0, OPEN_EXISTING, 0, 0);
    if (pHandleRead == System.IntPtr.Zero)
    {
        Win32Exception WE = new Win32Exception();
        ApplicationException AE = new ApplicationException("WinFileIO:OpenForReading - Could not open file " +
          FileName + " - " + WE.Message);
        throw AE;
    }
}


public void MoveOffset(int moveDistance, EMoveMethod moveMethod)
{
    if (pHandleRead != System.IntPtr.Zero)
    {
        int moveDistanceHigh = 0;
        SetFilePointer(pHandleRead, moveDistance, ref moveDistanceHigh, moveMethod);
    }
}


public unsafe Tuple<int, byte[]> ReadChunk(int bufferSize, int offset)
{
    int bytesRead = 0;
    byte[] bufBytes = new byte[bufferSize];
    MoveOffset(offset, EMoveMethod.Begin);
    int pointer = (int)Marshal.PtrToStructure(pHandleRead, typeof(int));

    if (ReadFile(pointer, bufBytes, bufferSize, ref bytesRead, null))
    {
        byte[] outBytes = new byte[bytesRead];
        Array.Copy(bufBytes, outBytes, bytesRead);
        return new Tuple<int, byte[]>(bytesRead, outBytes);
    }
    return null;
}

関連するコードはこれだけだと思います。

CreateFile および ReadFile 署名が完全に互換性がない (IntPtr と int)、IntPtr の Marshal.PtrToStructure が本来あるべき場所を指していない、またはメモリが解放されていないなどと関係があると思います。ただし、再起動後に数回試行しても機能しなかったという事実は、私を混乱させます。

誰でも明らかなことを見つけたり、私が調査できる提案はありますか?

ありがとう

編集:お気づきかもしれませんが、これはさまざまなアプローチの寄せ集めのようなものです。バッファの内容を必要なように読み取るのに苦労したため、ピン留めされたバッファはもう使用していません。

Edit2:スタックトレースは、これが問題であると言います:

at System.Runtime.InteropServices.Marshal.PtrToStructure(IntPtr ptr, Type structureType)
4

2 に答える 2

1

このコード

int pointer = (int)Marshal.PtrToStructure(pHandleRead, typeof(int));

あなたが思っていることをしません。pHandleReadこのコードは へのポインタとして扱われようとしますint。しかし、それはあなたが望んでいることではありません。あなたが望むことをするコードは次のとおりです。

int iHandleRead = pHandleRead.ToInt32();

実際、p/invoke 宣言が貧弱であるため、自分でそのコードを書いているだけです。宣言ReadFileでは、ファイル ハンドルを asIntPtrではなく asとして受け取る必要がありますint。その場合、上記のコードはまったく必要なく、合格しpHandleReadます。

より一般的なポイント:

  • unsafeここでコードを使用することを選択した理由がわかりません。ここではそれを必要とするものは何もありません。
  • また、このコードを機能させたとしても、同等のマネージド コードよりも優れたパフォーマンスを発揮する可能性は低いと思います。
于 2013-10-08T10:30:42.663 に答える