Debug.Assert not always working in c# - c#

I have a strange problem with Asserts being ignored. You can reproduce it with this minimal example. I am wondering why this problem occurs and how to face it:
public class TestAssert
{
public string EmptyString
{
get
{
System.Diagnostics.Debug.Assert(false);
return string.Empty;
}
}
Dictionary<string, object> dict = new Dictionary<string, object>();
public void ShowAssertIgnored()
{
var foo = dict[EmptyString];
}
}
You can see that the Debug.Assert(false) is ignored even though the property is evaluated. Just call
var test = new TestAssert();
test.ShowAssertIgnored();
and you should see what I mean (also shown on the image).
The code is compiled and run in Debug (other asserts work fine!), 32 bit, x86 + AnyCPU, VS2012 professional, .Net Framework 4
Edit:
The project is a console application and I was running it for several times in a row. Having a breakpoint before System.Diagnostics.Debug.Assert(false); most often a messagebox appears. But not always: When I just retry the same situation several times I sometimes see the result in the console.
To say it again: I can reproduce non-deterministic behaviour in the VS2012 debugger!

If you read the docs, you'll see that Debug.Assert isn't designed to throw.
Typically, the Assert(Boolean) method is used to identify logic errors during program development. Assert evaluates the condition. If the result is false, it sends a failure message to the Listeners collection. You can customize this behavior by adding a TraceListener to, or removing one from, the Listeners collection.
When the application runs in user interface mode, it displays a message box that shows the call stack with file and line numbers. The message box contains three buttons: Abort, Retry, and Ignore. Clicking the Abort button terminates the application. Clicking Retry sends you to the code in the debugger if your application is running in a debugger, or offers to open a debugger if it is not. Clicking Ignore continues with the next instruction in the code.
If running in an UI environment, it may trigger throw-like behaviour that is defined in the listeners that the UI environment/test-runner sets up.
So, in short, Debug.Assert(false) won't halt your application but its listeners might.
Assuming that there is no UI here... If you want your code to fail, then you'll need to write your own TraceListener:
public class MyTraceListener : TraceListener
{
public override void Write(string msg)
{
throw new Exception(msg);
}
public override void WriteLine(string msg)
{
throw new Exception(msg);
}
}
and add it to the listeners collection:
Debug.Listeners.Add(new MyTraceListener());

Have you checked your project settings to define the DEBUG constant? The Debug.Assert() methods have the [ConditionalAttribute("DEBUG")] attribute, which means, they will by ignored during compilation, if the "DEBUG" constant is not defined.

That's an expected behaviour, Debug.Assert() works in debug build only:
By default, the Debug.Assert method works only in debug builds. Use
the Trace.Assert method if you want to do assertions in release
builds. For more information, see Assertions in Managed Code.
https://msdn.microsoft.com/en-us/library/kssw4w7z(v=vs.110).aspx
use Trace.Assert() if you want it working in release as well.

Related

How to make [DebuggerNonUserCode] hide an exception from the debugger in simple test case?

Setup:
1) MSVS 2015, Option -> Debugger -> "Just My Code" is checked.
2) This sample code placed within some class and called during startup:
static bool TestIgnoreException()
{
Exception ex;
return TrySomething(out ex);
}
[DebuggerNonUserCode] // Prevent exceptions from stopping the debugger within this method.
static bool TrySomething(out Exception exOut)
{
try
{
if (Environment. MachineName.Length != -1)
throw new Exception("ThrewIt.");
exOut = null;
return true;
}
catch (Exception ex)
{
exOut = ex;
return false;
}
}
3) Launch Debugger
Expected result is that TestIgnoreException() runs silently and returns false.
Actual result is the debugger stops in TestIgnoreException() even though there should be no exception being processed at that scope.
4) Also re-tried using [DebuggerHidden] instead, same results.
Motivation:
The motivation is for cases where some API that is out of your control does not provide a "Try" method and instead only indicates failure by using exceptions.
One of numerous such examples is .NET TcpClient.Connect(host, port). Say a program always tests some connections during startup, the debugger should not stop on this particular section of code each time.
Using the standard "break when thrown" exceptions checkboxes is is not good because it works globally by type. It cannot be configured to work locally. Also other developers who check out the code should automatically skip the exception as well.
Mystery solved. It is indeed a known issue that is new to MSVS 2015 because of added exception handling optimizations.
https://blogs.msdn.microsoft.com/visualstudioalm/2016/02/12/using-the-debuggernonusercode-attribute-in-visual-studio-2015/#
There is a workaround posted on that link to disable the optimizations and enable the old behavior. Hopefully they will eventually be able to revive the support for this including the optimizations.
reg add HKCU\Software\Microsoft\VisualStudio\14.0_Config\Debugger\Engine /v AlwaysEnableExceptionCallbacksOutsideMyCode /t REG_DWORD /d 1
Related question:
Don't stop debugger at THAT exception when it's thrown and caught

LINQPad: Assert() prints "Fail:" and continues instead of breaking

In LINQPad, Debug.Assert() and Trace.Assert() from the System.Diagnostics namespace don't work as expected.
Instead of breaking - i.e. popping up a message box or whatever else happens to be configured for <trace> - they simply print "Fail:" or "Fehler:" to the output window and let the program continue on its merry way. In other words, instead of a noisy, unignorable explosion there are only near invisible micro-farts that intersperse "Fail:" into the textual output.
Is there any way of getting Assert() to revert to the default behaviour under LINQPad?
Alternatively, is there a simple way of mocking a Trace.Assert() so that failure results in a noisy explosion (i.e. exception, message box, whatever) and the source of the failure is pinpointed in the form of a line number or similar?
My unit tests are based on Trace.Assert(), which makes them totally useless if the function cannot break the program at the point of failure.
In Visual Studio everything works normally but not in LINQPad. I haven't fiddled with any system-wide settings but I did install Mono at some point in time. I went through all settings in LINQPad with a fine comb but to no avail. The LINQPad version is 4.57.02 (non-free), running on Windows 7 Pro (German) and Windows 8.1 Pro (English).
I googled high and wide but the only thing I could find is the topic Trace.Assert not breaking, neither showing the message box here on Stack Overflow. Its title certainly looks promising but the answers therein don't.
P.S.: I tried mocking by adding
class Trace
{
public static void Assert (bool condition)
{
if (!condition)
throw new Exception("FAIL!");
}
}
to the LINQ script and setting a breakpoint on the throw statement. Clicking on the relevant call stack entry in LINQPad's debugger takes me to the relevant source line, so this sort of works. However, I couldn't find an equivalent to FoxPro's SET DEBUG ON for invoking the debugger directly from the source code instead of having to set a breakpoint on the throw...
To answer the second half of your question, i.e., how do you get the LINQPad debugger to break when an exception is thrown, the answer is to click either of the 'Bug' icons on the toolbar.
Click Break when exception is unhandled (red bug) to make your query break whenever an unhandled exception is thrown.
Click Break when exception is thrown (blue bug) to make your query break whenever an exception is thrown, whether or not it is handled.
You can get LINQPad to make either setting the default by right-clicking and choosing Set as default. (Doing so forces the debugger to always attach to your queries, which incurs a small performance cost.)
As to why Debug.Assert(false) doesn't display a dialog, this is because this behavior hasn't been implemented in LINQPad. You could implement this easily as an extension, by adding the following code to My Extensions:
public class NoisyTracer : TextWriterTraceListener
{
public static void Install()
{
Trace.Listeners.Clear();
Trace.Listeners.Add (new NoisyTracer (Console.Out));
}
public NoisyTracer (TextWriter writer) : base (writer) { }
public override void Fail (string message, string detailMessage)
{
base.Fail (message, detailMessage);
throw new Exception ("Trace failure: " + message);
}
}
Then, to enable, write your query as follows:
NoisyTracer.Install();
Debug.Assert (false);

Environment.FailFast in c# application

I'd like to understand the Environment.FailFast rule in c# application. So , I made this code :
public static void Main()
{
string strInput = GetString();
Console.WriteLine(strInput);
Console.ReadKey();
}
private static string GetString()
{
Console.WriteLine("Get string");
string s = Console.ReadLine();
try
{
if (s == "Exit")
{
Environment.FailFast("Erreur fatale");
return s;
}
else
{
return s;
}
}
catch (Exception)
{
return "catch";
}
finally
{
s += "finally";
}
}
As I learned, the message are written to the Windows application event log and the application is terminated.
When I run the application and put Exit as a string :
The debbugger indicates an error :
I try to find the event log file, as indicated in msdn, but I don't find it
I don't understand why the application didn't shut down without throwing the exception? For the second point, How can I find the log file in my PC?
Environment.FailFast(string) exits the application immediately, without allowing any catch statements or finalizers to be run on the object.
You should only use this method if your application's state is at a point where it can never be recovered, and exiting the application is the only way to ensure something far worse than crashing does not happen. In your sample, using Environment.Exit with an exit code is more suitable, as it appears to be a graceful exit, rather than one forced through corrupt state.
In general, it is recommended to not use FailFast while the debugger is attached - this is documented in the System.Diagnostics.Assert class:
// However, in CLR v4, Environment.FailFast when a debugger is attached gives you an MDA
// saying you've hit a bug in the runtime or unsafe managed code, and this is most likely caused
// by heap corruption or a stack imbalance from COM Interop or P/Invoke. That extremely
// misleading error isn't right, and we can temporarily work around this by using Environment.Exit
// if a debugger is attached. The right fix is to plumb FailFast correctly through our native
// Watson code, adding in a TypeOfReportedError for fatal managed errors. We may want a contract-
// specific code path as well, using COR_E_CODECONTRACTFAILED.
Which means the exception you're seeing in Visual Studio is down to a bug in the CLR, and could be safely ignored.
Their work around is as follows:
if (Debugger.IsAttached)
Environment.Exit(COR_E_FAILFAST);
else
Environment.FailFast(message);
Which means that while running with the debugger attached, you won't get the Event Log message written, while in release you do.
I've reconstructed your problem with the following piece of code:
static void Main(string[] args)
{
try
{
Console.WriteLine("Foo");
Environment.FailFast("WOHO!");
}
finally { }
}
When running this under the debugger, I didn't see any exceptions registered either. Running this without the debugger (Ctrl + F5) makes the exception appear in the Event Viewer properly (see #aevitas answer or read this for why that happens):

Within my yield return function, if (false) is sending the control inside if's body [duplicate]

Given this gem of code:
class Program
{
private static bool IsAdmin = true;
static void Main(string[] args)
{
if (!IsAdmin)
{
throw new Exception();
}
try
{
var x = 2342342;
var y = 123132;
}
catch (Exception)
{
throw;
}
}
}
Given the this.IsAdmin yields true - I would expect the debugger to not enter that if statement. In reality it does - and it steps over the throw but does not actually throw!
Now this only happens when you have an exception inside an if statement followed by a try/catch block, on Visual Studio 2013, targeting .NET Framework 4, 64 bit, "Prefer 32 bit" unchecked.
I have confirmed this oddity with colleagues on different machines. Step though the following code and the debugger will seem to step into the if branch, but no exception is thrown:
I am in debug mode, I have tried compiling and cleaning the project multiple times.
Can anyone explain why this is happening?
This is a known problem caused by the x64 jitter, it occasionally generates bad debug line number info. It can fumble when a statement causes extra NOPs instructions to be generated, intended to align code. The first NOP becomes the line number, instead of the instruction after the NOPs. This bytes in a few places, like a throw statement after a simple if() test and usage of the ?? operator with simple scalar operands. These alignment NOPs are also the reason why it is so dangerous to abort threads, described in this post.
Simplest workaround is Project + Properties, Build tab, tick the "Prefer 32-bit" option if available, set the Platform target to x86 otherwise. Note how nothing actually goes wrong, while the debugger suggests that the throw statement is going to be executed your program doesn't actually throw an exception.
It is being worked on, the x64 jitter was drastically rewritten, a project named RyuJIT. It will ship in VS2015, currently in Preview.
Check out this link. It's a known bug in some versions of visual studio and the .NET framework version. It's completely harmless and something you will just have to live with.

Messagebox in Catch block not always showing [duplicate]

When I create a new project, I get a strange behavior for unhandled exceptions. This is how I can reproduce the problem:
1) create a new Windows Forms Application (C#, .NET Framework 4, VS2010)
2) add the following code to the Form1_Load handler:
int vara = 5, varb = 0;
int varc = vara / varb;
int vard = 7;
I would expect that VS breaks and shows an unhandled exception message at the second line. However, what happens is that the third line is just skipped without any message and the application keeps running.
I don't have this problem with my existing C# projects. So I guess that my new projects are created with some strange default settings.
Does anyone have an idea what's wrong with my project???
I tried checking the boxes in Debug->Exceptions. But then executions breaks even if I handle the exception in a try-catch block; which is also not what I want. If I remember correctly, there was a column called "unhandled exceptions" or something like this in this dialog box, which would do excatly what I want. But in my projects there is only one column ("Thrown").
This is a nasty problem induced by the wow64 emulation layer that allows 32-bit code to run on the 64-bit version of Windows 7. It swallows exceptions in the code that runs in response to a notification generated by the 64-bit window manager, like the Load event. Preventing the debugger from seeing it and stepping in. This problem is hard to fix, the Windows and DevDiv groups at Microsoft are pointing fingers back and forth. DevDiv can't do anything about it, Windows thinks it is the correct and documented behavior, mysterious as that sounds.
It is certainly documented but just about nobody understands the consequences or thinks it is reasonable behavior. Especially not when the window procedure is hidden from view of course, like it is in any project that uses wrapper classes to hide the window plumbing. Like any Winforms, WPF or MFC app. Underlying issue is Microsoft could not figure out how to flow exceptions from 32-bit code back to the 64-bit code that triggered the notification back to 32-bit code that tries to handle or debug the exception.
It is only a problem with a debugger attached, your code will bomb as usual without one.
Project > Properties > Build tab > Platform target = AnyCPU and untick Prefer 32-bit. Your app will now run as a 64-bit process, eliminating the wow64 failure mode. Some consequences, it disables Edit + Continue for VS versions prior to VS2013 and might not always be possible when you have a dependency on 32-bit code.
Other possible workarounds:
Debug > Exceptions > tick the Thrown box for CLR exceptions to force the debugger to stop at the line of code that throws the exception.
Write try/catch in the Load event handler and failfast in the catch block.
Use Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException) in the Main() method so that the exception trap in the message loop isn't disabled in debug mode. This however makes all unhandled exceptions hard to debug, the ThreadException event is pretty useless.
Consider if your code really belongs in the Load event handler. It is very rare to need it, it is however very popular in VB.NET and a swan song because it is the default event and a double-click trivially adds the event handler. You only ever really need Load when you are interested in the actual window size after user preferences and autoscaling is applied. Everything else belongs in the constructor.
Update to Windows 8 or later, they have this wow64 problem solved.
In my experience, I only see this issue when I'm running with a debugger attached. The application behaves the same when run standalone: the exception is not swallowed.
With the introduction of KB976038, you can make this work as you'd expect again. I never installed the hotfix, so I'm assuming it came as part of Win7 SP1.
This was mentioned in this post:
The case of the disappearing OnLoad exception – user-mode callback exceptions in x64
Here's some code that will enable the hotfix:
public static class Kernel32
{
public const uint PROCESS_CALLBACK_FILTER_ENABLED = 0x1;
[DllImport("Kernel32.dll")]
public static extern bool SetProcessUserModeExceptionPolicy(UInt32 dwFlags);
[DllImport("Kernel32.dll")]
public static extern bool GetProcessUserModeExceptionPolicy(out UInt32 lpFlags);
public static void DisableUMCallbackFilter() {
uint flags;
GetProcessUserModeExceptionPolicy(out flags);
flags &= ~PROCESS_CALLBACK_FILTER_ENABLED;
SetProcessUserModeExceptionPolicy(flags);
}
}
Call it at the beginning of your application:
[STAThread]
static void Main()
{
Kernel32.DisableUMCallbackFilter();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
I've confirmed (with the the simple example shown below) that this works, just as you'd expect.
protected override void OnLoad(EventArgs e) {
throw new Exception("BOOM"); // This will now get caught.
}
So, what I don't understand, is why it was previously impossible for the debugger to handle crossing kernel-mode stack frames, but with this hotfix, they somehow figured it out.
As Hans mentions, compile the application and run the exe without a debugger attached.
For me the problem was changing a Class property name that a BindingSource control was bound to. Running without the IDE I was able to see the error:
Cannot bind to the property or column SendWithoutProofReading on the
DataSource. Parameter name: dataMember
Fixing the BindingSource control to bind to the updated property name resolved the problem:
I'm using WPF and ran into this same problem. I had tried Hans 1-3 suggestions already, but didn't like them because studio wouldn't stop at where the error was (so I couldn't view my variables and see what was the problem).
So I tried Hans' 4th suggestion. I was suprised at how much of my code could be moved to the MainWindow constructor without any issue. Not sure why I got in the habit of putting so much logic in the Load event, but apparently much of it can be done in the ctor.
However, this had the same problem as 1-3. Errors that occur during the ctor for WPF get wrapped into a generic Xaml exception. (an inner exception has the real error, but again I wanted studio to just break at the actual trouble spot).
What ended up working for me was to create a thread, sleep 50ms, dispatch back to main thread and do what I need...
void Window_Loaded(object sender, RoutedEventArgs e)
{
new Thread(() =>
{
Thread.Sleep(50);
CrossThread(() => { OnWindowLoaded(); });
}).Start();
}
void CrossThread(Action a)
{
this.Dispatcher.BeginInvoke(a);
}
void OnWindowLoaded()
{
...do my thing...
This way studio would break right where an uncaught exception occurs.
A simple work-around could be if you can move your init code to another event like as Form_Shown which called later than Form_Load, and use a flag to run startup code at first form shown:
bool firstLoad = true; //flag to detect first form_shown
private void Form1_Load(object sender, EventArgs e)
{
//firstLoad = true;
//dowork(); //not execute initialization code here (postpone it to form_shown)
}
private void Form1_Shown(object sender, EventArgs e)
{
if (firstLoad) //simulate Form-Load
{
firstLoad = false;
dowork();
}
}
void dowork()
{
var f = File.OpenRead(#"D:\NoSuchFile756.123"); //this cause an exception!
}

Categories