I have an application running on the .Net framework 4 and my application runs managed AND unmanaged code. UDP sockets are used with a custom comms stack to speak with our custom hardware. When the application is run from Visual Studio, all is fine, but when it is run on its own, it often freezes. I have seen the behavior on both Windows XP SP3 and Windows 7 SP1. When the app is frozen, I can see that it is stuck in ntdll.dll in most of my threads. I was told in another question thread that this is normal, that the deadlock is still caused by my code.
This is very hard to debug, because I can only attach to the app and pause it in Native mode, so all I see is disassembly. I'm looking for any hint that could help me. So, does anyone have an idea what could cause an application to freeze when run directly vs. when run from Visual Studio using F5 ? I read some开发者_运维知识库where that, in managed code, the GC acts differently, what are the differences ? Also, for unmanaged code, I gathered that memory is initialized differently. Again what is the difference ?
Any help is greatly appreciated !
Seb
The one thing that's different when running the Release build without a debugger is that the JIT optimizer is enabled. The code runs faster. Which has a strong correlation with your problem, threading problems are timing sensitive. Count yourself lucky (I'm sure you don't) that this goes wrong while your code is still running on your dev machine, the really nasty threading problems are the ones mess up your program once a week on your customer's machines.
Making this problem debuggable is still the most important way to tackle it. Other than Tools + Attach to Process, another way to get the debugger started is by using System.Diagnostics.Debugger.Launch() in your code. You'll get a dialog that lets you choose the debugger.
Another way that doesn't require attaching the debugger is to switch VS to the Release build. Use Tools + Options, Debugging, General and untick "Suppress JIT optimization on module load". Pressing F5 now runs your program with the optimizer enabled and the debugger pre-attached. Still not quite a slamdunk since having the debugger attached in itself causes timing differences.
Another common approach to tackle difficult concurrency bugs is to add logging to your code. Write a line whenever it acquired a lock. With luck, you'll quickly find the deadlock reason. If you're not so lucky, the logging alters the thread timing enough to make the deadlock disappear. There have been plenty of programs shipped with logging left enabled because that was the only way to keep them running.
A code review is yet another approach, especially when done by somebody else. And last but not least, consider whether threading is really the optimal solution in your app. The nagging "did I really solve it?" feeling never goes away, proving that threaded code is free of defects is close to impossible.
A reason for such problems can be deadlocks or race conditions. They go away when you debug an application, because break points and execution breaks will change the execution duration of certain code paths.
I don't understand, why you can only attach in native mode. Even remote debugging is supported for managed applications.
精彩评论