Random AccessViolationExceptions

A

Andrus

VS2008 .net 3.5 WinForms application contains only managed code.
At random places my application causes exception below.

env: Vista SP1.

How to fix ?

Andrus.


System.AccessViolationException was unhandled
Message="Attempted to read or write protected memory. This is often an
indication that other memory is corrupt."
Source="System.Windows.Forms"
StackTrace:
at System.Windows.Forms.UnsafeNativeMethods.CallWindowProc(IntPtr
wndProc, IntPtr hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)
at System.Windows.Forms.NativeWindow.DefWndProc(Message& m)
at System.Windows.Forms.ToolTip.WndProc(Message& msg)
at System.Windows.Forms.ToolTip.ToolTipNativeWindow.WndProc(Message&
m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd,
Int32 msg, IntPtr wparam, IntPtr lparam)
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.Run(Form mainForm)
....
 
J

Jeroen Mostert

Andrus said:
VS2008 .net 3.5 WinForms application contains only managed code.
At random places my application causes exception below.

env: Vista SP1.

How to fix ?

Andrus.


System.AccessViolationException was unhandled
Message="Attempted to read or write protected memory. This is often an
indication that other memory is corrupt."
Source="System.Windows.Forms"
StackTrace:
at System.Windows.Forms.UnsafeNativeMethods.CallWindowProc(IntPtr
wndProc, IntPtr hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)

If some window proc is causing an access violation, then either there's a
bug in the window proc code itself (which is possible but unlikely if it's
pure managed code) or another application is subclassing windows or messing
with the dispatch logic improperly. A popular mistake is subclassing a
window with a dialog procedure pointing in a DLL, then having the DLL
unloaded somehow, resulting in a call to invalid memory.

Reboot in safe mode and see if the problem disappears. Or less drastically,
exit all programs that aren't necessary (including background programs) and
see if the problem disappears. You can use the "autoruns" tool
(http://technet.microsoft.com/sysinternals/bb963902) to get a list of
automatically starting programs and easily disable them.

If it's a third-party app, some trial and error should point you to the
culprit. If it's really a bug in the framework, good luck, these are a
little harder to diagnose and fix (or work around, as the case may be).

For problems like these, it pays to have a clean installation of Windows in
a virtual machine that you can use to verify that your application runs
correctly there. If it doesn't, you have to focus your efforts on that; if
it does, you know that the cause of failure is most likely something added
after a clean install, and you just have to find out what.
 
A

Andrus

If some window proc is causing an access violation, then either there's a
bug in the window proc code itself (which is possible but unlikely if it's
pure managed code) or another application is subclassing windows or
messing with the dispatch logic improperly. A popular mistake is
subclassing a window with a dialog procedure pointing in a DLL, then
having the DLL unloaded somehow, resulting in a call to invalid memory.

I use class WaitOper below in many places like

using (WaitOper waitOper = new WaitOper()) {
TimeConsumingOperation();
}

Can this usage cause this exception ?


class WaitOper : IDisposable
{
Cursor saveCursor;
internal WaitOper()
{
saveCursor = Cursor.Current;
Cursor.Current = Cursors.WaitCursor;
}

public void Dispose()
{
Cursor.Current = saveCursor;
GC.SuppressFinalize(this); // added since FxCop recommends
this.
}
}

Reboot in safe mode and see if the problem disappears. Or less
drastically, exit all programs that aren't necessary (including background
programs) and see if the problem disappears.

I do'nt have exact steps to reproduce so it is difficult to verify it it
disappers.

Andrus.
 
J

Jeroen Mostert

Andrus said:
I use class WaitOper below in many places like

using (WaitOper waitOper = new WaitOper()) {
TimeConsumingOperation();
}

Can this usage cause this exception ?
No. Managed code cannot (or should not be able to) cause access violations,
unless you use P/Invoke or unsafe operations, or the framework itself
contains a bug (this is rare but unfortunately not unheard of, and can be
damn annoying).
class WaitOper : IDisposable
{
Cursor saveCursor;
internal WaitOper()
{
saveCursor = Cursor.Current;
Cursor.Current = Cursors.WaitCursor;
}

public void Dispose()
{
Cursor.Current = saveCursor;
GC.SuppressFinalize(this); // added since FxCop recommends
this.

Your class doesn't have a finalizer, so you can remove the need for
..SuppressFinalize() by declaring your class sealed. If you know there will
be no subclasses to introduce a finalizer, you don't need to call
..SuppressFinalize() (FxCop will detect this).

Also, your class is already "internal" by default, so there's no need for
declaring the constructor internal. Declaring it public is less mysterious.

Aside from these nitpicks, this code shouldn't be causing you problems,
unless there's some subtle problem with cursors that I'm not aware of. Of
course, if you want to be sure, you can always stub out the class to see if
it helps.
I do'nt have exact steps to reproduce so it is difficult to verify it it
disappers.
That's always the hard part. There are several tools that may be of help.
One is AppVerifier (http://technet.microsoft.com/library/bb457063), which
may spot some problems an unseen unmanaged part of your application may be
causing. Failing that, you can always go for the all-out debugging option
with the Debugging Tools for Windows
(http://www.microsoft.com/whdc/devtools/debugging/) but there's a pretty
steep learning curve to the world of unmanaged debugging. Still, in catching
the access violation it might give you a good hint where the problem might be.
 
A

Andrus

If some window proc is causing an access violation, then either there's
I have managed dlls only. .NET does not allow to unload assemblies. How to
unload dll ?
Also, your class is already "internal" by default, so there's no need for
declaring the constructor internal. Declaring it public is less
mysterious.

If I remove internal keyword from constructor, a lot of

.... is inaccessible due to its protection level

compile errors occur since constructor becomes private. I use it from main
appl exe file only, so public
constructor is not required.
So I do'nt understand how it is reasonable to declare constructor not
internal.
That's always the hard part. There are several tools that may be of help.
One is AppVerifier (http://technet.microsoft.com/library/bb457063), which
may spot some problems an unseen unmanaged part of your application may be
causing.

Application does not start under AppVerifier. Vista shows:

myapp.exe stops working

and Cancel button.

AppVerifier shows message on save:

The tests you have selected for [myapp.exe] require a debugger and points to
page
http://www.microsoft.com/whdc/devtools/debugging/default.mspx

How I can use AppVerifier ?
Failing that, you can always go for the all-out debugging option
with the Debugging Tools for Windows
(http://www.microsoft.com/whdc/devtools/debugging/) but there's a pretty
steep learning curve to the world of unmanaged debugging. Still, in
catching the access violation it might give you a good hint where the
problem might be.

What should I install something from there to allow AppVerifier to work or
can I exclude some AppVerifier tests ?

I override ProcessCmdKey() in number of classes to implement custom keys in
winforms.

[SecurityPermission(SecurityAction.LinkDemand,
Flags = SecurityPermissionFlag.UnmanagedCode)]
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)

FxCop orders to add UnmamagedCode flag for this method in base classes. Can
this cause this exception ?

Andrus.
 
J

Jeroen Mostert

Andrus said:
I have managed dlls only. .NET does not allow to unload assemblies. How to
unload dll ?
Unmanaged DLLs could be injected into your application by any number of
components. You cannot unload these, as you cannot specifically check for
them, and even if you could, it wouldn't be safe. The only way to avoid
problems with an injected DLL is to make sure it doesn't get to inject
itself in the first place, hence the recommendation for testing it in safe mode.
If I remove internal keyword from constructor, a lot of

... is inaccessible due to its protection level

compile errors occur since constructor becomes private. I use it from main
appl exe file only, so public
constructor is not required.
So I do'nt understand how it is reasonable to declare constructor not
internal.
What I mean is this: because you've already declared the class itself as
"internal", the constructor is not accessible to clients outside the
assembly to begin with, as they can't even see the class. It's not *wrong*
to declare the constructor internal, but it's not *necessary* either. If you
ever decide to reuse the class and package it in a library, for example (in
other words, if you ever make the class public) the constructor will have to
be changed too.

To me, "internal" strongly implies "this member is tightly coupled with the
rest of the assembly". The class may be, but the constructor in particular
isn't.
Application does not start under AppVerifier. Vista shows:

myapp.exe stops working

and Cancel button.
That's moderately positive, as it could mean it's detected a problem.
AppVerifier shows message on save:

The tests you have selected for [myapp.exe] require a debugger and
points to
page
http://www.microsoft.com/whdc/devtools/debugging/default.mspx

How I can use AppVerifier ?
Start AppVerifier, add the application to the list of applications running
under AppVerifier. You can now exit AppVerifier.

Starting the application under a debugger is as simple as debugging it from
Visual Studio (this works if you point AppVerifier to the .exe in your
bin\Debug directory). You may need to check "enable unmanaged debugging" in
the project properties for this to work, though.

Visual Studio may not report all problems when using AppVerifier; the native
debuggers may be a better option.
What should I install something from there to allow AppVerifier to work or
can I exclude some AppVerifier tests ?
You really want to run the application under a debugger, whether it's Visual
Studio or the Debugging Tools for Windows. For one thing, the access
violation you're trying to diagnose is an exception that can only be
properly diagnosed under a debugger too.

The instructions for installation and use of the native debuggers are on the
page linked to.
I override ProcessCmdKey() in number of classes to implement custom keys in
winforms.

[SecurityPermission(SecurityAction.LinkDemand,
Flags = SecurityPermissionFlag.UnmanagedCode)]
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)

FxCop orders to add UnmamagedCode flag for this method in base classes. Can
this cause this exception ?
Not the flag itself. You can cause problems if you actually call unmanaged
or unsafe code in your override, or you modify the "msg" in such a way that
it's no longer valid (because one of the parameters holds a pointer, for
example).
 
A

Andrus

Unmanaged DLLs could be injected into your application by any number of
components. You cannot unload these, as you cannot specifically check for
them, and even if you could, it wouldn't be safe. The only way to avoid
problems with an injected DLL is to make sure it doesn't get to inject
itself in the first place, hence the recommendation for testing it in safe
mode.

I don't understand this: inject itself.
Does this mean that dll can load itself a second time ? How this can cause
access violation ?
How testing is safe mode can diagnose this ?
What I mean is this: because you've already declared the class itself as
"internal", the constructor is not accessible to clients outside the
assembly to begin with, as they can't even see the class. It's not *wrong*
to declare the constructor internal, but it's not *necessary* either. If
you ever decide to reuse the class and package it in a library, for
example (in other words, if you ever make the class public) the
constructor will have to be changed too.

I understand from this that marking internal class members internal instead
of public is not good practice.
If so, why compiler and FxCop does not report this ?
Starting the application under a debugger is as simple as debugging it
from Visual Studio (this works if you point AppVerifier to the .exe in
your bin\Debug directory). You may need to check "enable unmanaged
debugging" in the project properties for this to work, though.

I use C# Express 2008. I havent found "enable unmanaged debugging" checkbox
in project properties.
You really want to run the application under a debugger, whether it's
Visual Studio or the Debugging Tools for Windows. For one thing, the
access violation you're trying to diagnose is an exception that can only
be properly diagnosed under a debugger too.

I installed latest Debugging Tools and ran application under AppVerifier
using

"C:\Program Files\Debugging Tools for Windows (x86)\ntsd" myapp.exe

with Basic checkbox selected.
File Exit command in application causes breakpoint. ntsd window shows:

ModLoad: 75260000 752a5000 C:\Windows\system32\bcrypt.dll
ModLoad: 6ba40000 6ba5c000 SMDiagnostics.dll
ModLoad: 08680000 0869c000 SMDiagnostics.dll
ModLoad: 6ba40000 6ba5c000
C:\Windows\assembly\GAC_MSIL\SMDiagnostics\3.0.0.0_
_b77a5c561934e089\SMDiagnostics.dll
ModLoad: 6d930000 6d938000 MyApp.Resource.dll
ModLoad: 12250000 12258000 MyApp.Resource.dll
ModLoad: 6d930000 6d938000
I:\raamat\MyApp\MyApp\bin\Debug\MyApp.Resource.dll
ModLoad: 6d870000 6d878000 image6d870000
ModLoad: 12260000 12268000 image12260000
ModLoad: 6d870000 6d878000
I:\raamat\MyApp\MyApp\bin\Debug\en\MyApp.Resource.reso
urces.dll
ModLoad: 6b010000 6b016000 C:\Windows\system32\dciman32.dll
ModLoad: 74e30000 74e51000 C:\Windows\system32\NTMARTA.DLL
ModLoad: 755c0000 755d1000 C:\Windows\system32\SAMLIB.dll
(1f4.1468): Invalid handle - code c0000008 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=c0000008 ebx=00000000 ecx=0723f37c edx=772b9a38 esi=00000044
edi=00000000
eip=772b9a6f esp=0723f328 ebp=0723f378 iopl=0 nv up ei pl nz na pe
nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000
efl=00000206
ntdll!KiRaiseUserExceptionDispatcher+0x37:
772b9a6f 8b0424 mov eax,dword ptr [esp]
ss:0023:0723f328=c0000008
0:002>

App Verifier shows log below.
If I check all checkboxes in AppVerifier, exception occurs at starting.
ntsd also issues warning at startup:

Symbol search path is: *** Invalid ***
****************************************************************************
* Symbol loading may be unreliable without a symbol search path. *
* Use .symfix to have the debugger choose a symbol path. *
* After setting your symbol path, use .reload to refresh symbol locations. *
****************************************************************************
Executable search path is:
ModLoad: 10f10000 10f64000 MyApp.exe
ModLoad: 77260000 77387000 ntdll.dll
ModLoad: 6a220000 6a251000 C:\Windows\system32\verifier.dll
Page heap: pid 0x149C: page heap enabled with flags 0x3.
AVRF: eeva.exe: pid 0x149C: flags 0x80000181: application verifier enabled
ModLoad: 6d900000 6d928000 C:\Windows\system32\vrfcore.dll
ModLoad: 6d880000 6d8b9000 C:\Windows\system32\vfbasics.dll
ModLoad: 79000000 79046000 C:\Windows\system32\mscoree.dll
ModLoad: 76c30000 76d0b000 C:\Windows\system32\KERNEL32.dll
(149c.120c): Break instruction exception - code 80000003 (first chance)
eax=00000000 ebx=00000000 ecx=0023fa94 edx=772b9a94 esi=fffffffe
edi=772bb6f8
eip=772a7dfe esp=0023faac ebp=0023fadc iopl=0 nv up ei pl zr na pe
nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000
efl=00000246
*** ERROR: Symbol file could not be found. Defaulted to export symbols for
ntdl
l.dll -
ntdll!DbgBreakPoint:
772a7dfe cc int 3
0:000>

however current (Debug) directory contains pdb files created by C# Express.

How to diagnose problem from this infomation ?
Not the flag itself. You can cause problems if you actually call unmanaged
or unsafe code in your override, or you modify the "msg" in such a way
that it's no longer valid (because one of the parameters holds a pointer,
for example).

My method does not change msg parameter.
So I can assume that this cannnot cause access violation.

Andrus.


<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
- <avrf:logfile xmlns:avrf="Application Verifier">
- <avrf:logSession TimeStarted="2008-07-16 : 11:38:54" PID="5208"
Version="2">
- <avrf:logEntry Time="2008-07-16 : 11:39:04" LayerName="Handles"
StopCode="0x300" Severity="Error">
<avrf:message>Invalid handle exception for current stack
trace.</avrf:message>
<avrf:parameter1>c0000008 - Exception code.</avrf:parameter1>
<avrf:parameter2>6e7f178 - Exception record. Use .exr to display
it.</avrf:parameter2>
<avrf:parameter3>6e7f18c - Context record. Use .cxr to display
it.</avrf:parameter3>
<avrf:parameter4>0 - Not used.</avrf:parameter4>
- <avrf:stackTrace>
<avrf:trace>vfbasics!VfBasicsStopMessage+d1</avrf:trace>
<avrf:trace>vfbasics!AVrfpVectoredExceptionHandler+9b</avrf:trace>
<avrf:trace>ntdll!RtlGetProcessHeaps+13f</avrf:trace>
<avrf:trace>ntdll!RtlInitializeCriticalSectionAndSpinCount+164</avrf:trace>
<avrf:trace>ntdll!RtlInitializeCriticalSectionAndSpinCount+1d5</avrf:trace>
<avrf:trace>ntdll!KiUserExceptionDispatcher+f</avrf:trace>
<avrf:trace>ntdll!KiFastSystemCallRet+0</avrf:trace>
<avrf:trace>WS2_32!WSAUnhookBlockingHook+ada</avrf:trace>
<avrf:trace>WS2_32!send+4a</avrf:trace>
</avrf:stackTrace>
</avrf:logEntry>
</avrf:logSession>
</avrf:logfile>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top