What does it mean when a .NET application crashes

2020-07-18 04:46发布

问题:

The application itself is 2000 lines long so it wouldn't make sense to paste the code here, especially since the exception that one of the users received does not give any hints as to what part of my code is causing the problem.

The app, by the way, is just a Windows Form with a datagridview that typically displays no more than a few hundred rows of data, and some other controls. Before it crashed, it was loading the cells of each row of the datagridview extremely slowly. (But no other user has experienced the same problem.)

The exception text is below. Can someone please review it and tell me if it's caused by something that my code is doing wrong or perhaps something incompatible with the particular setup of the user who experienced this exception?

I notice that the description below says that memory is corrupt. Does it mean that the user's computer has bad RAM???

  ************** Exception Text **************
  System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
     at System.Drawing.SafeNativeMethods.Gdip.GdipDrawRectangleI(HandleRef graphics, HandleRef pen, Int32 x, Int32 y, Int32 width, Int32 height)
     at System.Drawing.Graphics.DrawRectangle(Pen pen, Int32 x, Int32 y, Int32 width, Int32 height)
     at System.Windows.Forms.ControlPaint.DrawFlatCheckBox(Graphics graphics, Rectangle rectangle, Color foreground, Brush background, ButtonState state)
     at System.Windows.Forms.ControlPaint.DrawFlatCheckBox(Graphics graphics, Rectangle rectangle, ButtonState state)
     at System.Windows.Forms.ControlPaint.DrawCheckBox(Graphics graphics, Int32 x, Int32 y, Int32 width, Int32 height, ButtonState state)
     at System.Windows.Forms.ControlPaint.DrawCheckBox(Graphics graphics, Rectangle rectangle, ButtonState state)
     at System.Windows.Forms.CheckedListBox.OnDrawItem(DrawItemEventArgs e)
     at System.Windows.Forms.ListBox.WmReflectDrawItem(Message& m)
     at System.Windows.Forms.ListBox.WndProc(Message& m)
     at System.Windows.Forms.CheckedListBox.WndProc(Message& m)
     at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
     at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
     at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

回答1:

Without more code, it's hard to say exactly. Here are some things to note.

.NET is a managed environment and one of its founding principles is the ability to validate code at compile time. Specifically, this means that certain guarantees may be made about a unit of code, such as:

  • Inability to read beyond the bounds of an array
  • Inability to modify function pointers
  • Inability to read/modify code segments of memory
  • Inability to confuse the type of an object reference

Attempting to do these will either fail at compile time, or at run time with an exception.

The exception you're seeing comes as a consequence of 'unsafe' code. Unsafe is a bit of a misnomer really -- it is better described as 'unverifiable'. Sometimes, for performance reasons, it's necessary to give up the verifiability of code in exchange for raw speed through things like pointer arithmetic.

this app has no unsafe code.

WinForms makes extensive use of 'unsafe' code. It's truer to say that your assembly doesn't have any unsafe code, but that it depends upon library code that is unsafe.

I notice that the description below says that memory is corrupt. Does it mean that the user's computer has bad RAM?

Bad RAM is a possibility, but quite unlikely. Memory is corrupt when the values expected to be there are not actually there. This can be due to hardware fault, but also to software errors. This exception is usually raised in response to software errors in my experience. Also the message says that memory might be corrupt.

The stack trace may not actually be very insightful here, as the memory is likely to have been corrupted at some earlier time, and was only detected during the stack frame you see here.

there is 1 platform invoke call to user32.dll's ShowWindow function (ShowWindow(p.MainWindowHandle, SW_SHOWDEFAULT);), but this call takes place before the message loop is started.

This may well be the culprit. Have you tried using the managed Window.Show method instead? It may be that your window doesn't have a handle yet, or that it changes, or that any number of things went wrong because of this. Generally try to avoid PInvoke when using managed wrappers on top of native stuff.

Unfortunately without seeing more of your code, it's impossible to provide a more useful answer, but hopefully the above provides some context onto the exception and may help you find out what your application is doing to get WinForms into this state.



回答2:

I want to mention this because this exception popped up for me and it took me a couple days to figure it out. I have no idea if the problem above is related, but maybe it will help someone who comes searching for said exception.

I was testing some logging code and once tests were checked in, we would see the exception pop up on the build server. We couldn't recreate it locally on our dev machines.

I decided to move the logic from the constructor to a method and all of a sudden the exception changed to System.EntryPointNotFoundException!

In our test harness, we were arranging objects using the System.WebAPI which was not being referenced by the logger. Referencing the right libraries fixed the issue.

TL;DR; Don't put your business logic in a Ctor and check your references when you see this exception.