我最近发布了一款Windows phone 8应用程序.该应用程序有时似乎随机崩溃,但问题是它崩溃没有破坏,我得到的唯一信息是输出上的消息,告诉我有一个访问冲突没有给出任何细节.因此,在发布后,我可以从崩溃报告中获得更多信息,但它们对我来说有点隐秘.
信息是:
Problem function: unknown //not very useful
Exception type: c0000005 //this is the code for Access violation exception
Stack trace:
Frame Image Function Offset
0 qcdx9um8960 0x00035426
1 qcdx9um8960 0x000227e2
Run Code Online (Sandbox Code Playgroud)
我不习惯使用内存指针和similia,我不习惯看到像这样的堆栈跟踪.
所以我有这样的问题:
笔记:
编辑:
我尝试将Debug类型设置为Native,这让我获得了与开发中心崩溃报告中相同的信息.这种方式调试器在抛出异常时中断并让我看到反汇编的代码,遗憾的是没有qcdx9um8960 .pdb文件(即使在Microsoft Symbol Server上),所以我不知道导致错误的函数名称.
我已经开始看到一个AccessViolationException被我的应用程序抛出了几个不同的位置.它从未出现在我的开发PC上,我们的测试服务器上.它也仅在我们的2个生产服务器中的一个上显示出来.因为它似乎只发生在我们的一个生产服务器上,所以我开始在服务器上查看已安装的.net框架版本.
我发现(出于一些奇怪的原因),出现问题的生产服务器有2.0 sp2,3.0 sp2和3.5 sp1,而另一个生产服务器和测试服务器有2.0 sp1.
我的应用程序仅针对2.0框架,决定从生产服务器卸载所有框架版本并仅安装2.0 sp1.到目前为止,我还没有能够重现这个问题.很有意思.
开发pc:紧凑型2.0 sp2,紧凑型3.5,2.0 sp2,3.0 sp2,3.5 sp1测试服务器:2.0 sp1生产服务器1:2.0 sp1生产服务器2:2.0 sp2,3.0 sp2,3.5 sp1
现在,为什么我无法重现问题我的开发pc上有2.0 sp2,我想不出来.我听说有传言说这种访问违规可能发生在一些使用远程处理的软件上,我的确如此,但是当实际进行远程处理时,访问冲突永远不会发生.我现在只使用2.0 sp1,但我真的很想知道是否有人遇到过这个问题,如果他们找到了更新版本的frameowork的解决方法.
这里有几个例外和它们的堆栈跟踪:
System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
at ICSharpCode.TextEditor.TextArea.HandleKeyPress(Char ch)
at ICSharpCode.TextEditor.TextArea.SimulateKeyPress(Char ch)
at ICSharpCode.TextEditor.TextArea.OnKeyPress(KeyPressEventArgs e)
at System.Windows.Forms.Control.ProcessKeyEventArgs(Message& m)
at System.Windows.Forms.Control.ProcessKeyMessage(Message& m)
at System.Windows.Forms.Control.WmKeyChar(Message& m)
at System.Windows.Forms.Control.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)
System.AccessViolationException: Attempted to read …Run Code Online (Sandbox Code Playgroud) 我们的应用程序经历了奇怪的致命System.AccessViolationException.我们看到这些因为我们已经配置了AppDomain.CurrentDomain.UnhandledException事件来记录异常.
Exception: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
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)
at Bootstrap.Run() in e:\build-dir\src\Bootstrap.cs:line 25
Run Code Online (Sandbox Code Playgroud)
异常本身似乎不包含比"尝试读取或写入受保护的内存"消息更多的信息.这通常表明其他内存已损坏.
UPDATE
非常有趣的是,以下C#代码将在.NET4.0上崩溃,但在.NET2.0上运行良好.
C#代码
class Program
{
static void Main(string[] args)
{
try
{
ExceptionTest();
Console.WriteLine("Done!");
}
catch (Exception e)
{
Console.WriteLine("Error !!!");
Console.WriteLine(e.Message);
}
}
[DllImport("badapp")]
private static extern int ExceptionTest();
}
Run Code Online (Sandbox Code Playgroud)
C++代码
extern "C" __declspec(dllexport) int ExceptionTest()
{
IUnknown* pUnk = NULL;
pUnk->AddRef();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如果针对.NET2.0编译上面的C#代码,一切正常.只针对.NET4.0进行编译会使其在运行时崩溃.
我怀疑自.NET4.0以来系统异常捕获机制已经改变.有任何想法吗?
出于教育目的,我正在编写一组方法,这些方法会导致C#中的运行时异常,以了解所有异常是什么以及导致它们的原因.现在,我正在修补导致问题的程序AccessViolationException.
对我来说最明显的方法是写入受保护的内存位置,如下所示:
System.Runtime.InteropServices.Marshal.WriteInt32(IntPtr.Zero, 0);
Run Code Online (Sandbox Code Playgroud)
正如我所希望的那样,这引起了人们的注意AccessViolationException.我想更简洁地做到这一点,所以我决定用不安全的代码编写程序,并通过分配0零指针来做(我认为的)完全相同的事情.
unsafe
{
*(int*)0 = 0;
}
Run Code Online (Sandbox Code Playgroud)
由于无法理解的原因,这引发了一个问题NullReferenceException.我玩了一些,并发现使用*(int*)1而不是抛出一个NullReferenceException,但如果你使用负数,就像*(int*)-1它会抛出一个AccessViolationException.
这里发生了什么?为什么*(int*)0 = 0导致a NullReferenceException,为什么不导致AccessViolationException?
我不知道如何调试这个.我有一个完全由托管代码组成的C#程序,在.NET 4.5中运行.运行一段时间后,在一些看似随机的时间,我得到一个错误"mscorlib.dll中发生了'System.AccessViolationException'类型未处理的异常".因为我是从Visual Studio(2012)运行的,所以我点击"break"并显示以下调用堆栈:
mscorlib.dll!System.Threading._IOCompletionCallback.PerformIOCompletionCallback(uint errorCode, uint numBytes, System.Threading.NativeOverlapped* pOVERLAP) + 0x47 bytes
[Native to Managed Transition]
ntdll.dll!_NtRequestWaitReplyPort@12() + 0xc bytes
kernel32.dll!_ConsoleClientCallServer@16() + 0x4f bytes
kernel32.dll!_GetConsoleLangId@4() + 0x2b bytes
kernel32.dll!_SetTEBLangID@0() + 0xf bytes
KernelBase.dll!_GetModuleHandleForUnicodeString@4() + 0x22 bytes
mdnsNSP.dll!7177aa48()
[Frames below may be incorrect and/or missing, no symbols loaded for mdnsNSP.dll]
mdnsNSP.dll!71775b06()
mdnsNSP.dll!71774ded()
mdnsNSP.dll!71774e8c()
bcryptprimitives.dll!746d1159()
bcryptprimitives.dll!746d1137()
ntdll.dll!_LdrpCallInitRoutine@16() + 0x14 bytes
ntdll.dll!_NtTestAlert@0() + 0xc bytes
ntdll.dll!_NtContinue@8() + 0xc bytes
ntdll.dll!_LdrInitializeThunk@8() + 0x1a bytes
Run Code Online (Sandbox Code Playgroud)
我注意到一个有趣的事情是调用堆栈中没有任何东西是我的代码.
你会建议我用什么策略来找到问题的路线?或者你有没有看到类似的问题并有任何提示?
由于异常似乎不包括我的代码,我不知道要包含什么信息有助于回答问题,但问我是否还有其他任何我应该包括的内容.
由于错误可能与IO相关(因为PerformIOCompletionCallback位于堆栈顶部),因此这是此应用程序执行的典型IO任务列表:
其他说明: …
与此问题相关,我想强制CLR让我的.NET 4.5.2应用程序捕获损坏的状态异常,其唯一目的是记录它们然后终止应用程序.如果我catch (Exception ex)在应用程序周围的几个地方,这样做的正确方法是什么?
因此,在我指定<legacyCorruptedStateExceptionsPolicy>属性后,如果我理解正确,所有catch (Exception ex)处理程序将捕获异常,AccessViolationException并愉快地继续.
是的,我知道catch (Exception ex)是一个坏主意™,但如果CLR至少将正确的堆栈跟踪放入事件日志中,我将非常乐意向客户解释他的服务器应用程序在凌晨1点快速失败并且离线晚上是件好事.但不幸的是,CLR将一个不相关的异常记录到事件日志中,然后关闭该过程,以便我无法找出实际发生的情况.
问题是,如何实现这一目标,流程广泛:
if the exception thrown is a Corrupted State Exception:
- write the message to the log file
- end the process
Run Code Online (Sandbox Code Playgroud)
(更新)
换句话说,这可能适用于简单应用中的大多数例外:
[HandleProcessCorruptedStateExceptions]
[SecurityCritical]
static void Main() // main entry point
{
try
{
}
catch (Exception ex)
{
// this will catch CSEs
}
}
Run Code Online (Sandbox Code Playgroud)
但是,它不适用于:
Main入口点)所以这似乎<legacyCorruptedStateExceptionsPolicy>是使这项工作成功的唯一方法,在这种情况下,我不知道在记录CSE后如何失败?
.net c# access-violation fail-fast corrupted-state-exception
在Delphi中编写应用程序时,您可以分享哪些提示来帮助查找和修复访问冲突?
我认为访问冲突通常是由于尝试访问尚未创建的内存中的某些内容(例如Object等)引起的?
我发现很难确定是什么触发了访问冲突,然后在哪里进行必要的更改以尝试停止/修复它们.
一个例子是我正在进行的个人项目.我在TTreeView Node.Data属性中存储了每个节点的一些数据.节点可以多次选择和导出(导出遍历每个选定节点并将特定数据保存到文本文件 - 保存到文本文件的信息是存储在nodes.data中的信息).文件也可以导入Treeview(将文本文件的内容保存到node.data中).
该示例中的问题是,如果我将文件导入Treeview然后导出它们,它就完美了.但是,如果我在运行时添加一个节点并导出它们,我得到:
"模块'Project1.exe'中地址00405772的访问冲突.读取地址00000388."
我对此的想法必须是我将数据分配给创建节点的方式,可能与导入时分配数据的方式不同,但这对我来说都很好.访问冲突仅在导出时显示,导入的文件不会发生这种情况.
我不是在寻找上述示例的修复程序,但主要是建议/提示如何查找和修复此类错误.我经常不会违反访问权限,但是当我这样做时,他们很难找到并修复.
所以建议和提示非常有用.
具体来说,是下面的代码,标记下方的行,好吗?
struct S{
int a;
};
#include <stdlib.h>
int main(){
struct S *p;
p = malloc(sizeof(struct S) + 1000);
// This line:
*(&(p->a) + 1) = 0;
}
Run Code Online (Sandbox Code Playgroud)
人们在这里争论,但没有人给出令人信服的解释或参考.
他们的论点略有不同,但基本相同
typedef struct _pack{
int64_t c;
} pack;
int main(){
pack *p;
char str[9] = "aaaaaaaa"; // Input
size_t len = offsetof(pack, c) + (strlen(str) + 1);
p = malloc(len);
// This line, with similar intention:
strcpy((char*)&(p->c), str);
// ^^^^^^^
Run Code Online (Sandbox Code Playgroud) 我试图从C#调用以下简单的C函数:
SIMPLEDLL_API const char* ReturnString()
{
return "Returning a static string!";
}
Run Code Online (Sandbox Code Playgroud)
使用以下P/Invoke声明(使用或不使用return属性,它没有区别):
[DllImport("SimpleDll")]
[return: MarshalAs(UnmanagedType.LPStr)]
public static extern string ReturnString();
Run Code Online (Sandbox Code Playgroud)
如果DLL是Debug构建但在Release构建(AccessViolationException)中崩溃,则它可以工作.
我正在调用十几个其他简单的函数,这是唯一失败的函数(这里是其他函数:)
[DllImport("SimpleDll")] public static extern int NextInt();
[DllImport("SimpleDll")] public static extern void SetNextInt(int x);
[DllImport("SimpleDll")] public static extern int AddInts(int a, int b);
[DllImport("SimpleDll")] public static extern int AddFourInts(int a, int b, int c, int d);
[DllImport("SimpleDll")] public static extern double AddDoubles(double x, double y);
[DllImport("SimpleDll")] public static extern IntPtr AddDoublesIndirect(ref double x, ref double y);
[DllImport("SimpleDll")] [return: …Run Code Online (Sandbox Code Playgroud) access-violation ×10
c# ×7
.net ×5
c++ ×2
c ×1
delphi ×1
exception ×1
fail-fast ×1
marshalling ×1
pinvoke ×1
pointers ×1
servicepacks ×1
struct ×1
unsafe ×1