C # CreatePipe () -> Ошибка защищенной памяти - PullRequest
3 голосов
/ 29 марта 2010

Я пытаюсь создать канал, используя C #. Код довольно прост, но я получаю сообщение об ошибке «Попытка чтения или записи защищенной памяти. Это часто указывает на повреждение другой памяти».

Вот полный код моей формы:

public partial class Form1 : Form
{
    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern bool CreatePipe(out SafeFileHandle hReadPipe, out SafeFileHandle hWritePipe, SECURITY_ATTRIBUTES lpPipeAttributes, int nSize);

    [StructLayout(LayoutKind.Sequential)]
    public struct SECURITY_ATTRIBUTES
    {
        public DWORD nLength;
        public IntPtr lpSecurityDescriptor;
        public bool bInheritHandle;
    }

    public Form1()
    {
        InitializeComponent();
    }

    private void btCreate_Click(object sender, EventArgs e)
    {
        SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();
        sa.nLength = (DWORD)System.Runtime.InteropServices.Marshal.SizeOf(sa);
        sa.lpSecurityDescriptor = IntPtr.Zero;
        sa.bInheritHandle = true;

        SafeFileHandle hWrite = null;
        SafeFileHandle hRead = null;

        if (CreatePipe(out hRead, out hWrite, sa, 4096))
        {
            MessageBox.Show("Pipe created !");
        }
        else
            MessageBox.Show("Error : Pipe not created !");
    }   
}

Вверху я заявляю: используя DWORD = System.UInt32;

Большое спасибо, если кто-то может помочь.

Ответы [ 2 ]

3 голосов
/ 29 марта 2010

Причиной нарушения защищенной памяти является то, что Windows API для CreatePipe ожидал значение указатель на область памяти, которую функция будет использовать в качестве плацдарма для структуры атрибутов безопасности. Простая передача в структуру SECURITY_ATTRIBUTES приведет к перезаписи защищенной памяти (страниц, еще не выделенных для вашего приложения), и, следовательно, ошибка защищенной памяти.

Передача IntPtr для представления этого указателя , решает вашу проблему.

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern bool CreatePipe(ref IntPtr hReadPipe, ref IntPtr hWritePipe, IntPtr  lpPipeAttributes, int nSize);

    [StructLayout(LayoutKind.Sequential)]
    public struct SECURITY_ATTRIBUTES
    {
        public DWORD nLength;
        public IntPtr lpSecurityDescriptor;
        [MarshalAs(UnmanagedType.Bool)]
        public bool bInheritHandle;
    }

    public Form1()
    {
        InitializeComponent();
    }

    private void btnCreate_Click(object sender, EventArgs e)
    {

        SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();
        sa.nLength = (DWORD)System.Runtime.InteropServices.Marshal.SizeOf(sa);
        sa.lpSecurityDescriptor = IntPtr.Zero;
        sa.bInheritHandle = true;

        IntPtr attr = Marshal.AllocHGlobal(Marshal.SizeOf(sa));
        Marshal.StructureToPtr(sa, attr, true);

        IntPtr hWrite = new IntPtr();
        IntPtr hRead = new IntPtr();

        if (CreatePipe(ref hRead, ref hWrite, attr, 4096))
        {
            MessageBox.Show("Pipe created !");
        }
        else
        {
            int error = Marshal.GetLastWin32Error();
            MessageBox.Show("Error : Pipe not created ! LastError= " + error);
        }
    }
2 голосов
/ 29 марта 2010

Просто измените объявление, чтобы SECURITY_ATTRIBUTES было указателем:

public static extern bool CreatePipe(out SafeFileHandle hReadPipe, out SafeFileHandle hWritePipe, ref SECURITY_ATTRIBUTES lpPipeAttributes, int nSize);
...