访问冲突:试图读取或写入受保护的内存

本文关键字:受保护 内存 读取 访问冲突 | 更新日期: 2023-09-27 18:08:59

我有一个c# (.net 4.0) winforms应用程序,它几乎每周都在XP SP 3上运行,每天8小时。大多数时候都很好,有时可以持续几个月。然后它似乎陷入了一个糟糕的状态,每天一次,连续几天,在不同的时间,出现了访问冲突异常。我试过查看转储文件,并捕获访问违反异常来查看堆栈;无论哪种方式,我都得到了几乎相同的堆栈:

Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
   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.Callback(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(IntPtr 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)

我很难修复这个问题,因为堆栈跟踪不是很有用。首先,我甚至不确定我是否可以信任堆栈跟踪:程序到达那里(看起来像是试图显示一些工具提示,这当然是可能的)是因为内存已经损坏,或者如果程序真的应该在那里,但是一些数据内存损坏了。第二,假设堆栈跟踪是正确和可信的,我不认为有办法找出是什么破坏了内存…我们没有做任何导致访问违规的事情……在此之前,应用程序日志不显示任何其他捕获的异常…事件日志不显示任何条目在访问冲突的同时…关于如何进一步诊断有什么提示吗?

更新2011-10-11:我已经捕捉到异常,但在Application.Run()方法周围。在这一点上,似乎已经太迟了。如果这个异常是由于硬件/驱动程序故障而发生的,并且不表明应用程序的内存损坏——是否还有其他地方可以捕获异常(并显示它,但然后让应用程序继续)?

更新2012-03-04:我又得到了异常,这一次显示了一个相当平凡的表单(只包含一个文本框和一个ok按钮)。我使用的是TextBox.AppendText()。我只是碰巧在同一时间浏览了这条评论。AppendText()会导致这个问题吗?当"原始"访问违规发生时,它们往往发生在显示包含richtextbox的表单之后,我也调用了AppendText()。情节越来越复杂了!

更新2012-03-06:我删除了AppendText,只使用TextBox。文本=,但我今天又得到了访问冲突异常。因此,AppendText似乎不是罪魁祸首。此外,该异常在运行Windows 7的开发盒上发生过一次。因此,这个异常似乎不是特定于Windows XP或其他计算机(如内存问题)的。

访问冲突:试图读取或写入受保护的内存

多亏了这篇文章,我才能够重复这个问题。因此,一个解决方法似乎是使用datagridview禁用所有datagridview中的所有工具提示。ShowCellToolTips = false;然而,这并不理想。一个更好的解决方法是调用

Application.EnableVisualStyles();

在应用程序中创建任何控件之前。

我已经确认,问题发生是否DataGridView显示自定义工具提示(与CellToolTipTextNeeded)或不。

我在调用C dll的第三方c#包装器时观察到这个问题。我禁用DEP为c# dll,使用实用程序editbin.exe/NXCOMPAT:NO {dll名称},似乎已经解决了这个问题。

当DEP打开时,CLR应该做额外的检查,并且C dll可能正在做CLR认为是内存损坏的事情并抛出此错误。

你可以阅读更多关于这个,http://blogs.msdn.com/b/ed_maurer/archive/2007/12/14/nxcompat-and-the-c-compiler.aspx

我们最近也得到了一个AccessViolationException当做TextBox.AppendText()。在尝试重现问题后,我们意识到文本框不是问题所在。在我们的例子中是拖放功能。

下面是一个最小的项目(一个带有TextBox的表单),它将重现异常:

using System;
using System.Windows.Forms;
namespace TestTextBoxAccessViolation {
    public partial class Form1 : Form {

        public Form1() {
            InitializeComponent();
        }
        private void Form1_DragEnter(object sender, DragEventArgs e) {
            e.Effect = DragDropEffects.Copy;
        }
        private void Form1_DragDrop(object sender, DragEventArgs e) {
            e.Data.GetData("DragImageBits");
            Form1 f = new Form1();
            f.textBox1.Text = "Keep resizing this window and you'll get an AccessViolationException after a while";
            f.Show();
        }
    }
}
结论:不要使用"DragImageBits"。

我发现这个问题不仅发生在WPF中,而且发生在WinForms中。我的问题与OpenFileDialog有关。很难说问题的根源是什么,但似乎与OpenFileDialog相关的Microsoft dll存在错误(对我来说,它是ComDlg32.dll)

调用ShowDialog()函数的唯一方法是将其封装在事件中,并在

的帮助下调用
this.BeginInvoke(
        new Action<YourObject, EventArgs>(YourObject_FileDialogOpened), new object[] 
                                                        { YourObjectInstance, e });

,其中"this"是控件(例如,Form)。

BeginInvoke(…)授予你的调用将以适当的方式被处理。

如果您在按钮单击事件或任何其他类似场景下使用OpenFileDialog调用,则不会出现问题。

不确定这是否会有所帮助,但这个问题似乎在旧版本的。net中很常见,微软甚至发布了一些修复程序。

其中一个初始修复如下:

http://support.microsoft.com/kb/923028

这是另一个。http://support.microsoft.com/kb/975954

这并不容易跟踪/修复,因为所有的信息都是相当"通用"的,所以这些是一些通用的指针:

  • 总是发生在同一台机器上吗?
    如果是,那么检查机器(内存测试等,从可引导的linux CD或类似的运行)和/或在不同的机器上运行它,看看它是否发生了变化。

  • 在显示工具提示时似乎发生了异常…可能是显卡驱动程序有问题…选择不同的驱动程序和/或不同的屏幕分辨率等,看看会发生什么

  • 是否使用第三方库?
    如果是这样的话,检查它们是否存在非托管内存问题(例如使用内存分析器……)是值得的。请与供应商确认是否有更新的版本等。
    我以前有过类似的事情,结果证明是一些第三方库中的非托管内存泄漏(通过内存分析器诊断)…我和供应商联系了一下,得到了一个固定的版本,从那时起就运行得很顺利。

我遇到了与op相同的行为。我修改了一个软件并添加了两个PInvoke方法(以改进UI)。不幸的是,我开始收到和op一样的信息。在查看答案时,我发现了Raja Hindustani的。注释掉这两个PInvoke方法后,问题似乎消失了。

相关文章: