我在点击处理程序中有一个简单的函数,它有一个 try catch 块。如果我在此 try catch 块中抛出异常,它会成功捕获异常。
如果我在抛出异常之前调用非托管 DLL,则异常不会被处理且不会被捕获。
未修改的 DLL 调用正在做什么,可能会破坏我的程序异常处理?
如果我在调试模式下运行程序,即使所有异常都未勾选“异常中断”,它也会捕获异常。应用程序不会崩溃并按预期运行。
如果我以“启动而不调试”的方式运行程序,并在崩溃时点击调试,则会收到以下错误“堆栈 cookie 检测代码检测到基于堆栈的缓冲区溢出”
edit:看来堆栈溢出破坏了异常处理
我附上了一个产生崩溃的简化程序。
ISOConnection _comm; //This is instantiated at another time in the same thread
//C# test function that crashes when run without a debugger attached
bool DoMagic()
{
try
{
//if I uncomment this line the exception becomes unhandled and cannot be caught
//_comm.ConnectISO15765();
throw new Exception();
}
catch (Exception ex)
{
MessageBox.Show("Caught exception")
}
//Within ISOConnection class
public void ConnectISO15765(){
...
lock(syncLock){
uint returnCode = J2534Interface.PassThruConnect((uint)DeviceId, (uint)ProtocolID.ISO15765, (uint)ConnectFlag.NONE, (uint)BaudRate.ISO15765, ref ChannelId);
//C# UnmanagedFunctionPointer allocation code
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate uint PassThruConnect(uint deviceId, uint protocolId, uint flags, uint baudRate, ref uint channelId);
public PassThruConnect Connect;
[DllImport("kernel32.dll")]
public static extern IntPtr LoadLibrary(string dllToLoad);
m_pDll = NativeMethods.LoadLibrary(path);
...
pAddressOfFunctionToCall = NativeMethods.GetProcAddress(m_pDll, "PassThruConnect");
if (pAddressOfFunctionToCall != IntPtr.Zero)
Connect = (PassThruConnect)Marshal.GetDelegateForFunctionPointer(
pAddressOfFunctionToCall,
typeof(PassThruConnect));
//C++ function declaration
long PassThruConnect(unsigned long DeviceID, unsigned long ProtocolID, unsigned long Flags, unsigned long Baudrate, unsigned long *pChannelID);
UPDATE
如果我用以下内容替换对 UnmanagedFunctionPointer PassThurConnect 的调用,则不会发生崩溃
[DllImport("op20pt32.dll", EntryPoint = "PassThruConnect", CallingConvention = CallingConvention.Cdecl)]
public static extern uint PassThruConnect2(uint deviceId, uint protocolId, uint flags, uint baudRate, ref uint channelId);
在分配 UnmanagedFunctionPointer 时是否有什么我没有执行或执行不正确会导致缺少调试器而导致 stackoverflow 崩溃?
更奇怪的是,这段代码在几周前似乎可以工作。主要的变化是 try catch 在另一个线程中,并且我没有使用锁(syncLock)。现在所有内容都在一个线程中,但是在后台工作程序中运行时也会发生相同的崩溃。
更新 #2 问题已半解决
好吧,我一一回滚了我的提交,直到它起作用为止。改变的是我从 .NET 3.5 转到 .NET 4.0
无论是否附加调试器,.NET 3.5 都不会崩溃。如果未附加调试器,.NET 4.0 会崩溃。为了排除代码中的错误,我只是删除了日志的 ConcurrentQueue(我使用的唯一 4.0 功能)并将当前的代码库转换回 3.5,并且我没有收到此错误。
为了百分百确定这是 4.0 的问题,我随后将代码库从 3.5 转换回 4.0,并保留了 ConcurrentQueue(实际上只是更改了构建选项并进行了重建),StackOverflow 崩溃又回来了。
我更喜欢使用 4.0,有什么想法如何调试这个问题吗?
编辑:.NET 4.6.1 也崩溃
更新#3
http://codenition.blogspot.com.au/2010/05/pinvokestackimbalance-in-net-40i-beg.html http://codenition.blogspot.com.au/2010/05/pinvokestackimbalance-in-net-40i-beg.html
显然 pinvokestackimbalance 在 .NET 3.5 中基本上被忽略了,所以问题仍然存在,它只是不会使我的应用程序崩溃。
将以下代码添加到 App.Config 会导致 .NET 在转换回托管代码时修复堆栈。虽然性能受到一点影响,但可以解决问题。
虽然这确实解决了问题,但我想知道我的 UnmanagedFunctionPointer 出了什么问题导致了问题。
<configuration>
<runtime>
<NetFx40_PInvokeStackResilience enabled="1"/>
编辑:该线程不是重复的,另一个已被删除......