David Monaghan
David Monaghan

Reputation: 29

Crashing: Attempted to read or write protected memory c#

We have a periodic crashing problem with our software. I think I have tracked down where it is happening but I am unfamiliar with the code. It's extremely difficult to debug.

We cannot reproduce this problem on our development environment, it happens on our live environment. The users log in to our system with swipe cards, the terminals have magnetic swipe readers. It happens maybe once a day when they swipe a card. The MSR is read like a keyboard.

I have swiped a card a few hundred times in a row on different occasions and have had no issues on dev.

There is try catch but it doesn't catch anything, the error we are getting in event viewer is:

"Attempted to read or write protected memory. This is often an indication that other memory is corrupt."

Here is the function I am pretty sure it's crashing in:

    private void GetRawInputInfo(
        IntPtr rawInputHeader,
        ref IntPtr deviceHandle,
        ref bool handled,
        ref StringBuilder buffer)
    {
        try
        {
            uint cbSize = 0;
            IntPtr hRawInput;

            hRawInput = rawInputHeader;


            if (UnsafeNativeMethods.GetRawInputData(
                hRawInput,
                Structures.RAWINPUTDATAUICOMMAND.RID_INPUT,
                IntPtr.Zero,
                ref cbSize,
                (uint)Marshal.SizeOf(typeof(Structures.RAWINPUTHEADER))) == 0)
            {
                IntPtr ptr = Marshal.AllocHGlobal((int)cbSize);

                if (ptr != IntPtr.Zero &&
                    UnsafeNativeMethods.GetRawInputData(
                        hRawInput,
                        Structures.RAWINPUTDATAUICOMMAND.RID_INPUT,
                        ptr,
                        ref cbSize,
                        (uint)Marshal.SizeOf(typeof(Structures.RAWINPUTHEADER))) == cbSize)
                {

                    Structures.RAWINPUT raw = (Structures.RAWINPUT)Marshal.PtrToStructure(ptr, typeof(Structures.RAWINPUT));

                    deviceHandle = raw.header.hDevice;
                    handled = raw.header.dwType == Structures.RAWINPUTDEVICEDWTYPE.RIM_TYPEKEYBOARD &&
                        raw.keyboard.Message == Messages.WM_KEYDOWN;

                    if (handled)
                    {
                        byte[] state = new byte[256];

                        // Force the keyboard status cache to update
                        UnsafeNativeMethods.GetKeyState(0);

                        // Note: GetKeyboardState only returns valid state when
                        // the application has focus -- this is why we weren't
                        // getting shift keys when the application was not focused
                        if (UnsafeNativeMethods.GetKeyboardState(state))
                        {
                            //StringBuilder unmanagedBuffer = new StringBuilder(64);

                            if (UnsafeNativeMethods.ToUnicode(
                                raw.keyboard.VKey,
                                raw.keyboard.MakeCode,
                                state,
                                buffer,
                                64,
                                0) <= 0)
                            {
                                buffer.Remove(0, buffer.Length);
                            }
                        }
                    }
                }
                if (ptr != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(ptr);
                }
            }
        }
        catch (Exception e)
        {
            BLog.LogError("Error running: GetRawInputInfo()" + e.Message);
        }
    }

Any help or pointers (pun intended) in the right direction would be appreciated,

Thanks

----Updated:

Here is the call stack if this helps in any way:

Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)

at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)

at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)

at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)

at System.Windows.Forms.Application.RunDialog(Form form)

at System.Windows.Forms.Form.ShowDialog(IWin32Window owner)

at System.Windows.Forms.Form.ShowDialog()

at MyApplication.UI.BaseDisplay.ShowDialog(SecurityData security, Int32 listViewState, Nullable`1 ticketId, Int32 currentSeatPosition)

I have made the changes as per Matt and will see if there is any change in the crashing but it may take a day or 2. Sometimes it doesn't crash every day, but generally there is one every day.

Upvotes: 1

Views: 3963

Answers (2)

Jon Tackabury
Jon Tackabury

Reputation: 49319

This is a bit late, but I have had this exact issue with the ToUnicode function in C#. We never did figure out how to make the function work without crashing randomly, so we avoid it like the plague.

Upvotes: 0

SageMage
SageMage

Reputation: 1106

If the application were to throw an exception somewhere between Marshal.AllocHGlobal((int)cbSize) and Marshal.FreeHGlobal(ptr) you could end up with some memory issues eventually causing your application to crash expectantly.

To remedy the situation I would recommend declaring the IntPtr ptr above the first if statement and then after your catch block use the finally block to check that the ptr variable isn't null and then call Marshal.FreeHGlobal(ptr).

While this may or may not solve your issue, It would be a good idea to ensure that the memory is ALWAYS de-allocated.

Code would look as follows

private void GetRawInputInfo(
        IntPtr rawInputHeader,
        ref IntPtr deviceHandle,
        ref bool handled,
        ref StringBuilder buffer)
    {
        try
        {
            uint cbSize = 0;
            IntPtr hRawInput;
            IntPtr ptr;

            hRawInput = rawInputHeader;


            if (UnsafeNativeMethods.GetRawInputData(
                hRawInput,
                Structures.RAWINPUTDATAUICOMMAND.RID_INPUT,
                IntPtr.Zero,
                ref cbSize,
                (uint)Marshal.SizeOf(typeof(Structures.RAWINPUTHEADER))) == 0)
            {
                ptr = Marshal.AllocHGlobal((int)cbSize);

                if (ptr != IntPtr.Zero &&
                    UnsafeNativeMethods.GetRawInputData(
                    hRawInput,
                    Structures.RAWINPUTDATAUICOMMAND.RID_INPUT,
                    ptr,
                    ref cbSize,
                    (uint)Marshal.SizeOf(typeof(Structures.RAWINPUTHEADER))) == cbSize)
            {

                Structures.RAWINPUT raw = (Structures.RAWINPUT)Marshal.PtrToStructure(ptr, typeof(Structures.RAWINPUT));

                deviceHandle = raw.header.hDevice;
                handled = raw.header.dwType == Structures.RAWINPUTDEVICEDWTYPE.RIM_TYPEKEYBOARD &&
                    raw.keyboard.Message == Messages.WM_KEYDOWN;

                if (handled)
                {
                    byte[] state = new byte[256];

                    // Force the keyboard status cache to update
                    UnsafeNativeMethods.GetKeyState(0);

                    // Note: GetKeyboardState only returns valid state when
                    // the application has focus -- this is why we weren't
                    // getting shift keys when the application was not focused
                    if (UnsafeNativeMethods.GetKeyboardState(state))
                    {
                        //StringBuilder unmanagedBuffer = new StringBuilder(64);

                        if (UnsafeNativeMethods.ToUnicode(
                            raw.keyboard.VKey,
                            raw.keyboard.MakeCode,
                            state,
                            buffer,
                            64,
                            0) <= 0)
                        {
                            buffer.Remove(0, buffer.Length);
                        }
                    }
                }
            }
        }
    }
    catch (Exception e)
    {
        BLog.LogError("Error running: GetRawInputInfo()" + e.Message);
    }
    finally
    {
        if (ptr != IntPtr.Zero)
            Marshal.FreeHGlobal(ptr);
    }
}

Upvotes: 2

Related Questions