关于调试尝试使用 winform 读取或写入受保护内存异常的建议
一些背景知识,该应用程序是一个打印应用程序,在 Autodesk 程序 REvit Structure 中运行。它是一个 .net 插件。
我一直被这些间歇性出现的异常所困扰,这真的很令人沮丧。我该如何调试这些?
一般来说,建议在 Revit 插件中不要使用多线程,在这个特定实例中我所做的就是从 Revit 读取一些信息,然后在缺少某些信息时显示一个对话框。我不知道为什么会导致 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.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.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)
所以在按钮上您可以看到我的 FilePostProicessor.SetParameters 方法是引发消息框的地方。但是,当发生这种情况时,一堆其他东西会继续与引发事件(Windows 窗体代码的一部分?)有关,然后顶部有一些我不知道的 Autodesk 东西。
我还注意到 'ExceptionWrapper.InternalRealCall' 确实对我有帮助,是否有一个我可以看到的实际异常对我来说有一半用处?
我在这里做错了什么吗?我的代码只是单线程循环一些东西。
我意识到这对于你们来说“boom line 358 是你们的问题”来说并不是很多信息,但是任何关于调试/避免这些类型的错误的建议都会有帮助。虽然我使用 dsofile.dll 在文件上设置一些自定义属性,但我没有做任何非托管的事情,但这是我正在做的事情上面的几行代码,我认为它是单线程的?
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.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.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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我想您可能会在这里看到重入问题。该对话框会发送 Windows 消息,在本例中是回调到 Autodesk。 Autodesk 或许并不希望被召回——它可能处于糟糕的状态。
您可以尝试创建一个新线程来运行对话框。
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.
我不熟悉 Revit,但在 AutoCAD 中,如果创建临时图形对象,则必须将它们添加到图形中或在对象上显式调用 .Dispose。关于 .NET 垃圾收集器如何在另一个线程上自动运行以及 AutoCAD 析构函数不是线程安全的。因此,任何被 .NET 垃圾收集器清理的孤立 AutoCAD 对象都会导致程序失败。这可能不是您的问题,但无论如何还是需要检查一下。
否则,我还了解到此错误可能是由非托管代码中格式不正确的函数调用引起的,就像错误所暗示的那样,会破坏程序内存。您对此无能为力。因此,该错误的棘手部分是,原因可能是很久以前发生的,并且抛出异常的位置只是一个无辜的受害者,并且无法让您知道哪个函数调用造成了原始损坏。
我还了解到,禁用编译器优化并在构建中包含调试信息可以掩盖问题。关于当调试信息包含在构建中时,内存损坏只会覆盖调试元数据而不是程序数据,因此不会修复错误,只是防止它造成损坏。
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.