advice on debugging attempt to read or write protected memory exception with winforms
Some background, this application is a printing application that runs within REvit Structure, an Autodesk program. Its a .net add-in.
I have been plagued with these sort of exceptions that pop up intermittently and it is really frustrating. How can I go about debugging these?
Generally it is advised multi-threading is not used in Revit add-ins, and all I'm doing in this particular instance is reading some information from Revit and then showing a dialog box if there was some information missing. I don't know why that causes AccessVioldationExceptions
Unhandled exception!: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.; StackTrace: at CCmdUI.DoUpdate(CCmdUI* , CCmdTarget* , Int32 )
at CTestCmdUI.computeEnabled(CTestCmdUI* , CCmdTarget* pTarget)
at UIFrameworkServices.CommandHandlerService.canExecute(String strName)
at UIFramework.CommandUtility.CanExecute(RibbonCommandItem btn)
at UIFramework.RibbonGlobalHandler.CanExecute(Object parameter)
at Autodesk.Windows.InternalCommands.CanExecuteGenericCommand(Object sender, CanExecuteRoutedEventArgs args)
at System.Windows.Input.CommandBinding.OnCanExecute(Object sender, CanExecuteRoutedEventArgs e)
at System.Windows.Input.CommandManager.FindCommandBinding(CommandBindingCollection commandBindings, Object sender, RoutedEventArgs e, ICommand command, Boolean execute)
at System.Windows.Input.CommandManager.FindCommandBinding(Object sender, RoutedEventArgs e, ICommand command, Boolean execute)
at System.Windows.Input.CommandManager.OnCanExecute(Object sender, CanExecuteRoutedEventArgs e)
at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
at System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted)
at System.Windows.Input.RoutedCommand.CanExecuteImpl(Object parameter, IInputElement target, Boolean trusted, Boolean& continueRouting)
at System.Windows.Input.RoutedCommand.CanExecute(Object parameter, IInputElement target)
at MS.Internal.Commands.CommandHelpers.CanExecuteCommandSource(ICommandSource commandSource)
at System.Windows.Controls.Primitives.ButtonBase.UpdateCanExecute()
at System.Windows.Input.CommandManager.CallWeakReferenceHandlers(List`1 handlers)
at System.Windows.Input.CommandManager.RaiseRequerySuggested(Object obj)
at System.Windows.Threading.Ex开发者_如何学CceptionWrapper.InternalRealCall(Delegate callback, Object args, Boolean isSingleParameter)
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler)
at System.Windows.Threading.DispatcherOperation.InvokeImpl()
at System.Threading.ExecutionContext.runTryCode(Object userData)
at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Windows.Threading.DispatcherOperation.Invoke()
at System.Windows.Threading.Dispatcher.ProcessQueue()
at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Boolean isSingleParameter)
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler)
at System.Windows.Threading.Dispatcher.InvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Boolean isSingleParameter)
at MS.Win32.HwndSubclass.SubclassWndProc(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.Form.ShowDialog(IWin32Window owner)
at BWTools.ErrorDisplayer.DisplayErrorWithoutLogging(String message) in C:\devel\Revit Macros\2011\BWTools\ErrorDisplayer.cs:line 93
at Plotting.Printers.FilePostProcessor.SetParameters(IDictionary`2 sheetLocations, ParameterGrabber grabber, FilePrintSettings settings) in C:\devel\Revit Macros\2011\PLT2\Plotting\Printers\FilePostProcessor.cs:line 277
at Plotting.Printers.FilePostProcessor.ProcessSheets(IList`1 sheets, String extension, String finalLocation, ParameterGrabber grabber, FilePrintSettings settings) in C:\devel\Revit Macros\2011\PLT2\Plotting\Printers\FilePostProcessor.cs:line 37
at Plotting.Printers.PdfPrinter.Print(PrintSelection selection, FilePrintSettings settings) in C:\devel\Revit Macros\2011\PLT2\Plotting\Printers\PdfPrinter.cs:line 68
at Plotting.Printers.PdfPrinter.Print(PrintSelection selections, PrintSettings settings) in C:\devel\Revit Macros\2011\PLT2\Plotting\Printers\PdfPrinter.cs:line 112
at Plotting.GuiControl.Print() in C:\devel\Revit Macros\2011\PLT2\Plotting\Gui\GuiControl.cs:line 148
at Plotting.Gui.PrintingSplash.animationTimer_Tick(Object sender, EventArgs e) in C:\devel\Revit Macros\2011\PLT2\Plotting\Gui\PrintingSplash.xaml.cs:line 51
at System.Windows.Forms.Timer.OnTick(EventArgs e)
at System.Windows.Forms.Timer.TimerNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
So at the button you can see my FilePostProicessor.SetParameters method is where the messagebox is being raised from. But when that happens a bunch of other stuff goes on to do with Raising Events (part of windows forms code?) and then there is some Autodesk stuff at the top which I don't know about.
Also I noticed 'ExceptionWrapper.InternalRealCall' does that help me out at all, is there an actual exception somewhere I can see that is half useful for me?
Is there something I'm doing wrong here? My code is just single threaded looping through some stuff.
I realise this isn't a lot of information for you guys to say 'boom line 358 is your problem' but any advice on debugging/avoiding these types of errors would be helpful. I'm not doing anything unmanaged though I am using dsofile.dll to set some custom properties on a file, but that is a few lines of code above what I'm doing and I think its single threaded?
I think you might be seeing a re-entrancy problem here. The dialog pumps windows messages, which in this case is calling back into autodesk. Autodesk perhaps does not expect to be called back into--it may be in a bad state.
You might try creating a new thread for the dialog to run in.
I'm not familiar with Revit, but in AutoCAD if you create temporary drawing objects, you have to either add them to the drawing or explicitly call .Dispose on the object. Something about how the .NET garbage collector automatically runs on another thread and the AutoCAD destructors are not thread-safe. So any orphaned AutoCAD objects that get cleaned up by the .NET garbase collector cause the program to fail. This may not be your issue but its something to check anyway.
Otherwise I have also read that this error can be caused by incorrectly formed function calls in un-managed code that, like the error suggests, currupts program memory. There may not be much you can do about it. So the tricky part of the error is that the cause could have happends a long time ago and the location of where the exception is thrown is just an innocent victim and gives you no clue as to what function call did the original damage.
I also read that disabling compiler optimizations and including debugging information in the build can mask the issue. Something about how when debug info is included in the build, the memory corruption will just overrite debugging meta data instead of program data, thus not fixing the error just preventing it from doing damage.
精彩评论