我们从本机代码抛出了非确定性的System.AccessViolationException.重现它很难,但有时它会发生.我不确定我是否可以"只调试它",因为访问冲突所需的时间大约是2小时,并且无法保证会发生访问冲突.
托管包装器使用本机库.它从java到JNI使用,它从.NET到IKVM的JNI使用.该问题仅在IKVM代码期间重现,但数据集不同,无法使用IKVM应用程序使用的数据测试Java应用程序.
我有一切的来源,但(如果可能的话)我想避免进行大量的更改.
我相信本机调用堆栈将提供有关此访问冲突原因的足够信息.
有没有有效的方法来确定此访问违规的原因?
我认为对我来说理想的解决方案是代码或进程环境中的一些更改,因此在发生此访问冲突时会因内存转储而崩溃,因此我可以进行更改并等待.
所以我有一个我正在使用的本地第三方C++代码库(.lib和.hpp文件),我曾经在C++/CLI中构建一个包装器,以便最终在C#中使用.
从调试模式切换到发布模式时,我遇到了一个特殊问题,因为当回调代码返回时,我遇到了一个访问冲突异常.
来自原始hpp文件的代码用于回调函数格式:
typedef int (*CallbackFunction) (void *inst, const void *data);
Run Code Online (Sandbox Code Playgroud)
来自C++/CLI Wrapper的代码用于回调函数格式:(我将解释为什么我暂时宣布两个)
public delegate int ManagedCallbackFunction (IntPtr oInst, const IntPtr oData);
public delegate int UnManagedCallbackFunction (void* inst, const void* data);
Run Code Online (Sandbox Code Playgroud)
- 很快,我宣布第二个"UnManagedCallbackFunction"的原因是我试图在包装器中创建一个"中间"回调,因此链从Native C++> C#更改为Native C++> C++/CLI Wrapper> C#的版本...完全公开,问题仍然存在,它刚刚被推送到C++/CLI Wrapper现在在同一行(返回).
最后,来自C#的崩溃代码:
public static int hReceiveLogEvent(IntPtr pInstance, IntPtr pData)
{
Console.WriteLine("in hReceiveLogEvent...");
Console.WriteLine("pInstance: {0}", pInstance);
Console.WriteLine("pData: {0}", pData);
// provide object context for static member function
helloworld hw = (helloworld)GCHandle.FromIntPtr(pInstance).Target;
if (hw == null || pData == null)
{
Console.WriteLine("hReceiveLogEvent: received …Run Code Online (Sandbox Code Playgroud) 我有一个ac#(.net 4.0)winforms应用程序,每天每天工作8小时,在XP SP 3上运行.它在大多数情况下工作正常,有时持续数月.然后它似乎陷入了一个糟糕的咒语,并且每天一次,连续几天,在不同的时间,出现访问冲突异常.我已经尝试查看转储文件,并捕获访问冲突异常以查看堆栈; 无论哪种方式,我得到几乎相同的堆栈:
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)
Run Code Online (Sandbox Code Playgroud)
我很难解决这个问题,因为堆栈跟踪不是很有用.首先,我甚至不确定我是否可以信任堆栈跟踪:程序是否到达那里(看起来它正在尝试显示一些工具提示,这当然是可能的)因为内存已经损坏,或者程序确实应该合法地那里,但有些数据内存已损坏.其次,假设堆栈跟踪是正确且值得信赖的,我没有找到一种方法来弄清楚什么是破坏内存...我们没有做任何一致的事情来触发访问冲突...应用程序日志没有显示任何在此之前其他被捕获的异常...事件日志不会与访问冲突同时显示任何条目...有关如何进一步诊断此问题的任何提示?
更新2011-10-11:我已经捕获了异常,但围绕Application.Run()方法.那时似乎为时已晚太多了.如果由于硬件/驱动程序错误而发生此异常并且未指示应用程序的内存已损坏 - 是否还有其他地方可以捕获异常(并显示它,然后让应用程序继续)?
更新2012-03-04:我再次获得异常,这次显示一个相当简单的表单(只包含一个文本框和一个ok按钮).我使用的是TextBox.AppendText().我恰巧正在同时浏览这条评论 …
我正在使用Delphi 6,我有一个应用程序,当关闭时会产生访问冲突错误.我们使用EurekaLog,因此我得到了用于调试的堆栈跟踪,但错误似乎每次都在不同的单元中随机出现,但总是在最终化部分中释放某些内容时.
我怎样才能调试这个以查看导致问题的原因?我不确定如何开始调试应用程序最终确定时发生的事情.
[编辑:]对不起,如果我不清楚,或许更好的问题是:如果我只想完成最终确定部分,那么开始使用断点进行调试的最佳位置是什么?这些错误似乎出现在我们使用的第三方组件(devexpress dx/cxgrid库)中,所以我想在Delphi开始在其他单元中调用finalize例程之前的最后一点开始调试我的代码.
我在以下代码中收到意外的访问冲突错误:
program Project65;
{$APPTYPE CONSOLE}
{$R *.res}
uses
SysUtils;
type
ITest = interface
end;
TTest = class(TInterfacedObject, ITest)
end;
var
p: ^ITest;
begin
GetMem(p, SizeOf(ITest));
p^ := TTest.Create; // AV here
try
finally
p^ := nil;
FreeMem(p);
end;
end.
Run Code Online (Sandbox Code Playgroud)
我知道接口应该以不同的方式使用.但是我正在研究使用这种方法的遗留代码库.而且我很惊讶地发现,保留SizeOf(ITest)内存并将ITest放在那里是不够的.
现在有趣的是,如果我改变第一行
GetMem(p, 21);
Run Code Online (Sandbox Code Playgroud)
比AV消失了.(20个字节或更少的失败).对此有何解释?
(我使用的是Delphi XE2 Update 4 + HotFix)
请不要评论代码是多么可怕或建议如何正确编码.请回答为什么有必要保留21个字节而不是SizeOf(ITest)= 4?
我在IIS 6服务器中实现和ASP .Net应用程序时遇到了麻烦.
当用户尝试打开访问数据库的网页时,iis服务器会抛出"尝试读取或写入受保护的内存"这是StackTrace:
System.AccessViolationException:尝试读取或写入受保护的内存.这通常表明其他内存已损坏.at Oracle.DataAccess.Client.OpsPrm.ResetValCtx(OpoPrmValCtx*pOpoPrmValCtx,Int32 ctxSize),位于Oracle.DataAccess.Client.OracleParameter.PreBind(OracleConnection conn,IntPtr errCtx,Int32)的Oracle.DataAccess.Client.OracleParameter.ResetCtx(Int32 arraySize)在Tenaris.FSA的Oracle.DataAccess.Client.OracleCommand.ExecuteScalar()上的Oracle.DataAccess.Client.OracleCommand.ExecuteReader()处的Oracle.DataAccess.Client.OracleCommand.ExecuteReader(布尔请求,布尔fillRequest,CommandBehavior行为)中的arraySize) .OracleProvider.OracleProvider.ExecuteScalar(String commandToExecute,CommandType commandType,DbParameter []参数)在C:\ Congelados FSA\FSA 1er中可入侵05052013\Tenaris.FSA.OracleProvider\OracleProvider.cs:第223行在Tenaris.FSA.DAC.Providers C:\ Congelados FSA\FSA 1er中的.DataAccessManager.ExecuteScalar(String commandToExecute,CommandType commandType,DbParameter []参数)Entvable 05052013\Tenaris.FSA.DataAccessComponent\Providers\DataAccessManager.cs:第59行a t Tenaris.FSA.DAC.Repository.AppointmentWayClientDAL.GetCountRegisters(Boolean onlyEnabled)位于C:\ Congelados FSA\FSA 1er Entregable 05052013\Tenaris.FSA.DataAccessComponent\Repository\AppointmentWayClientDAL.cs:第39行:Tenaris.FSA.BusinessComponents.BusinessProcess .AppointmentWayClientManager.GetCountRegisters(Boolean onlyEnabled)在C:\ Congelados FSA\FSA 1er Entregable 05052013\Tenaris.FSA.BusinessComponents\BusinessProcess\AppointmentWayClientManager.cs:第28行
什么是罕见的,因为该错误不应该出现在托管代码中,并且该站点的先前版本工作正常.我做了几个测试,比如在x86平台电脑上编译应用程序,从功能版本复制web.config,从功能版本复制Oracle.DataAccess dll,但错误仍然显示.
您应该知道的另一件事是,有一个页面实际上已经成功填写了一个下拉列表,但是页面必须填充gridview并且出现上述异常.
简而言之,我有一个C#应用程序执行大量mciSendString调用(通过dllimport)来控制wav文件播放(基本上是打开,播放,暂停,停止,状态,关闭).运行一段时间后,应用程序崩溃,恕不另行通知"访问冲突".
即使我从我的vs2012运行应用程序,视觉工作室也没有抓住异常.即使有'强行突破异常'选项,我也没有运气从vs2012调试这个.所以我设置WER来生成崩溃转储,我使用windbg和psscor2.dll插件来调试它.
然后按顺序,使用以下命令,这是我得到的(为了可读性而缩短为必要的):
$>.ecxr
eax=00000001 ebx=00000000 ecx=00000401 edx=00000000 esi=049725b8 edi=00000002
eip=4e88159e esp=0a4efa38 ebp=0a4efa54 iopl=0 nv up ei pl nz ac pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010216
<Unloaded_mciwave.dll>+0x159e:
4e88159e ?? ???
Run Code Online (Sandbox Code Playgroud)
$>〜*KB
# 19 Id: 105c.28cc Suspend: 1 Teb: 7ef06000
Unfrozen
user32!NtUserGetMessage+0x15
user32!GetMessageA+0xa1
winmm!mciwindow+0x102
kernel32!BaseThreadInitThunk+0xe
ntdll!__RtlUserThreadStart+0x70
ntdll!_RtlUserThreadStart+0x1b
# 30 Id: 105c.15f8 Suspend: 0 Teb: 7ef1b000 Unfrozen
ntdll!ZwWaitForMultipleObjects+0x15
KERNELBASE!WaitForMultipleObjectsEx+0x100
kernel32!WaitForMultipleObjectsExImplementation+0xe0
kernel32!WaitForMultipleObjects+0x18
kernel32!WerpReportFaultInternal+0x186
kernel32!WerpReportFault+0x70
kernel32!BasepReportFault+0x20
kernel32!UnhandledExceptionFilter+0x1af
ntdll!__RtlUserThreadStart+0x62
ntdll!_EH4_CallFilterFunc+0x12
ntdll!_except_handler4+0x8e
ntdll!ExecuteHandler2+0x26
ntdll!ExecuteHandler+0x24
ntdll!RtlDispatchException+0x127
ntdll!KiUserExceptionDispatcher+0xf
WARNING: Frame IP not in any known …Run Code Online (Sandbox Code Playgroud) 我在初始化列表中使用QString时遇到了访问冲突,我不明白.
这是一个重现问题的最小例子.
// file ClassA.h
#pragma once
#include <QString>
struct Parameter
{
QString stringPar;
};
class ClassA
{
QString m_string1;
public:
void function(Parameter pars);
};
Run Code Online (Sandbox Code Playgroud)
ClassA的实施......
// file ClassA.cpp
#include "ClassA.h"
void ClassA::function(Parameter pars)
{
m_string1 = pars.stringPar; // last line called in my code when the crash happens
}
Run Code Online (Sandbox Code Playgroud)
和main.cpp
// file main.cpp
#include "ClassA.h"
int main()
{
ClassA classA;
classA.function({ QString("jkjsdghdkjhgdjufgskhdbfgskzh") });
// when using this code the problem does not occur
//Parameter par = { QString("jkjsdghdkjhgdjufgskhdbfgskzh") }; …Run Code Online (Sandbox Code Playgroud) 申请/代码说明:
我的应用程序基于c#并使用SQL Server CE,并且在同一代码位置只有两次获得此异常.直到此版本才引入此例外的崩溃.此版本中唯一的变化是将.net框架更改为4.5.2.
我在处理a时遇到访问冲突异常SqlCeConnection,出现以下错误:
尝试读取或写入受保护的内存.这通常表明其他内存已损坏.
此异常不会被.net的try catch子句拦截 - 它会导致崩溃.
在我的代码中,我使用以下命令运行
try
{
var connectionString = string.Format("{0}{1}{2}", "Data Source=", _localDB, ";File Mode=Read Write;Max Database Size=4000;Persist Security Info=False;");
using (var sqlCeConnection = new SqlCeConnection(connectionString))
{
using (var sqlCeCommand = new SqlCeCommand())
{
sqlCeCommand.Connection = sqlCeConnection;
sqlCeCommand.CommandText = "SELECT * FROM Application";
sqlCeConnection.Open();
var result = (string)sqlCeCommand.ExecuteScalar();
isValid = !IsValid(result);
}
}
}
catch (Exception ex)
{
_log.Error("exception", ex);
}
Run Code Online (Sandbox Code Playgroud)
第一次崩溃的调用堆栈:
ntdll!ZwWaitForMultipleObjects+a
KERNELBASE!WaitForMultipleObjectsEx+e8
kernel32!WaitForMultipleObjectsExImplementation+b3
kernel32!WerpReportFaultInternal+215
kernel32!WerpReportFault+77
kernel32!BasepReportFault+1f
kernel32!UnhandledExceptionFilter+1fc
ntdll! ?? …Run Code Online (Sandbox Code Playgroud) 我试图在我的应用程序中捕获所有未处理的异常,以便我可以在它们出现时保存日志文件.这是一个使用Visual Studio 2013编译的64位Windows应用程序,用C++编写.为了测试我使用VS生成的默认C++ Win32项目.
我通过使用SetUnhandledExceptionFilter注册处理程序来捕获所有异常.这适用于/大多数/案例,但不是全部.捕获所有throw() - n异常,以及大多数硬件异常,例如浮点或访问冲突.不触发处理程序的代码是:
std::vector<int> foo(5, 0);
for (auto& f : foo)
foo.erase(foo.begin() + 1);
Run Code Online (Sandbox Code Playgroud)
相反,我只是获得标准的Windows崩溃对话框,而不会调用异常处理程序.但是,如果我在附带调试器的Visual Studio中运行它,它会正确报告访问冲突异常.其他类型的访问冲突也会触发处理程序:
float* ptr = nullptr;
float value = *ptr;
Run Code Online (Sandbox Code Playgroud)
上面的代码触发异常处理程序.
我也尝试过使用try/catch或捕获SIGSEGV信号,但是第一个例子都没有触发.中止/终止信号也不会被调用.简而言之,当崩溃发生时,我不会得到通知.
我想知道是否有任何方法可以在我的应用程序中获得某种通知,然后由于第一个示例导致的访问冲突而崩溃?由于VS似乎能够检测到它,我假设有一种方法.
编辑:我只想说明我在发布模式下运行代码,第一个示例中的错误不是由调试模式下的迭代器超出边界检查引起的.
EDIT2:我包含了一个最简单的例子,我可以使用win32控制台应用程序.请在此处查看:http: //pastebin.com/8L1SN5PQ
确保在未附带调试器的发布模式下运行它.