Whenever a unit test fails due to a StackOverflowException the unit test process immediately exits - the only way to find out what happened (that I am aware of) is to debug a crash dump of the unit test process obtained by following the steps found here
Collecting User-Mode Dumps
What is the easiest way of getting the name of the unit test that was running at the time that the StackOverflowException was thrown? Even when debugging the unit test I'm struggling to find the name of the current unit test as its at the bottom of the stack and Visual Studio wont' shown the entire stack in the debugging window because its too large.
Is there some way to find out which unit test failed without collecting and debugging crash dumps?
As mentioned in this other question, you can't really catch a stack overflow exception unless you throw it yourself.
So, as a workaround to your problem (not really a solution) you can insert a method call in you code to detect a stack overflow, then throw the exception manually and catch it later.
[TestClass]
public class TestStackOverflowDetection
{
[TestMethod]
public void TestDetectStackOverflow()
{
try
{
InfiniteRecursion();
}
catch (StackOverflowException e)
{
Debug.WriteLine(e);
}
}
private static int InfiniteRecursion(int i = 0)
{
// Insert the following call in all methods that
// we suspect could be part of an infinite recursion
CheckForStackOverflow();
// Force an infinite recursion
var j = InfiniteRecursion(i) + 1;
return j;
}
private static void CheckForStackOverflow()
{
var stack = new System.Diagnostics.StackTrace(true);
if (stack.FrameCount > 1000) // Set stack limit to 1,000 calls
{
// Output last 10 frames in the stack
foreach (var f in stack.GetFrames().Reverse().Take(30).Reverse())
Debug.Write("\tat " + f);
// Throw a stack overflow exception
throw new StackOverflowException();
}
}
Take a look at RuntimeHelpers.EnsureSufficientExecutionStack method (http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.runtimehelpers.ensuresufficientexecutionstack.aspx). You might want to call it in your recursive method(s) to get InsufficientExecutionStackException ahead of time.
Related
We know that the code in the finally block is guaranteed to execute, regardless of whether the exception is caught. But let's say we have the following code:
class Program {
static void Main(string[] args) {
try {
int a = 0;
int b = 2021 / a;
}
finally {
System.Diagnostics.Debug.WriteLine("finally execute");
}
}
}
I cannot use Console.WriteLine since an unhandled exception terminates a process, no output written to the console, so I use System.Diagnostics.Debug.WriteLine, hopefully I can see "finally execute" displayed in the VS debug window.
When I execute the code, I didn't find "finally execute" in debug window, which means finally block won't execute if there is an unhandled exception.
If you look at this link https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/try-finally
It does say:
Part one
Within a handled exception, the associated finally block is guaranteed to be run. However, if the exception is unhandled, execution of the finally block is dependent on how the exception unwind operation is triggered. That, in turn, is dependent on how your computer is set up.
Part Two
The only cases where finally clauses don't run involve a program being immediately stopped. An example of this would be when InvalidProgramException gets thrown because of the IL statements being corrupt. On most operating systems, reasonable resource cleanup will take place as part of stopping and unloading the process.
My questions are:
Q1-What does "dependent on how your computer is set up" in Part One mean?
Q2-If it is dependent on how the computer is set up, then what does Part Two mean? The exception in my example is DivideByZeroException, not InvalidProgramException, so why the finllay block still doesn't execute
As per my understanding finally will execute in this case. As you have not use Catch block it throw unhandled exception to the process level so any statement after finally block will not execute.
This is the code.
using System;
namespace ConsoleApp3
{
class Program
{
static void Main(string[] args)
{
try
{
int a = 0;
int b = 2021 / a;
}
finally
{
Console.WriteLine("finally execute");
}
Console.WriteLine("Complete");
Console.ReadLine();
}
}
}
Sample output.
I have this console application (.NET Framework 4.5.2):
class Program
{
static void Main(string[] args)
{
using (var result = new Result())
{
result.Test();
}
}
}
public class Result : IDisposable
{
public void Test()
{
int a = 1;
int b = 1 / (a - 1);
}
public void Dispose()
{
Console.WriteLine("Dispose");
}
}
Why Dispose method is not called? A breakpoint is not hit in Dispose after the DivideByZero-exception and there is no output on the console (because the app exits).
As per MS Docs: try-finally (C# Reference)
Within a handled exception, the associated finally block is guaranteed
to be run. However, if the exception is unhandled, execution of the
finally block is dependent on how the exception unwind operation is
triggered. That, in turn, is dependent on how your computer is set up.
As you are not catching the DivideByZero exception and let it be unhandled, on your machine and setup it must be bringing down the application before any other line of code is run and therefore not running the finally block.
As #Evk has pointed out in below comment, if I run it without attaching debugger, it unwinds the exceptions correctly and executes the finally block. Learn something new everyday.
As per Eric Lippert's answer to Finally Block Not Running?
Think about how awful that situation is: something unexpected has
happened that no one ever wrote code to handle. Is the right thing to
do in that situation to run even more code, that was probably also not
built to handle this situation? Possibly not. Often the right thing to
do here is to not attempt to run the finally blocks because doing so
will make a bad situation even worse. You already know the process is
going down; put it out of its misery immediately.
In a scenario where an unhandled exception is going to take down the
process, anything can happen. It is implementation-defined what
happens in this case: whether the error is reported to Windows error
reporting, whether a debugger starts up, and so on. The CLR is
perfectly within its rights to attempt to run finally blocks, and is
also perfectly within its rights to fail fast. In this scenario all
bets are off; different implementations can choose to do different
things.
I'm using testing in my code, and by my understanding, all a test requires to run in a method is this:
private ClassName(Argument)
{
return;
}
So what the test is actually checking is if the "Argument" is the correct output at the end of the method/test.
However in my case the argument passed in has nothing to do with the output. Therefore I am uncertain of how to test it.
NOTE: The code itself is sound, it outputs the correct variables. Also I actually wrote the test after the code (Big booboo, I know. I want to get into the habit of always testing.)
EDIT: I believe the issue is to do with the Test being exited via the LoginView.Close and LoginView.Menu.SetMenuView. (The function ends on this line, and the test cannot complete?)
The Location of the return; also affects the rest of the code, so it needs to be at the end of the code. If I move it up, the rest of the code becomes unreachable, and the program breaks.
I have looked for ways to try and bypass the exceptions, and all I have come up with is to test that the exception is actually being thrown correctly. Is there a way to bypass the exception in the test?
Here is the test:
public void Compare_LoginTest()
{
User_LoginView LoginView = new User_LoginView();
User_Controller.screenName = "ben";
User_Controller.screenPwd = "password";
User_Controller.Compare_Login(LoginView);
int actual = User_Controller.screenAccess;
int expected = 1;
Assert.AreEqual(expected, actual);
}
Here is the method being tested:
public static void Compare_Login(User_LoginView LoginView)
{
// Creates a new oject of User_Model and populates it from the User_Controller.
User_Model AccessModel = new User_Model();
AccessModel.Name = screenName;
AccessModel.Pwd = screenPwd;
// Runs the Login Comparsion in the Database_Facade, and passes in the Model.
Database_Facade Database = new Database_Facade();
Database.GetLoginAccess(AccessModel);
screenAccess = AccessModel.AccessLevel;
Menu_View.accessLevelSet = AccessModel.AccessLevel;
// Compares the returned AccessLevel.
// if it is corect; closes the Login and runs the SetMenuView method,
// if it is incorrect; shows an error.
if (AccessModel.AccessLevel > 0)
{
Console.WriteLine("Access Level " + AccessModel.AccessLevel);
// Exception Thrown in testing.
LoginView.Close();
LoginView.Menu.SetMenuView();
}
else
{
ErrorCodes_Controller LoginError = new ErrorCodes_Controller();
LoginError.WrongLoginError();
}
return;
}
I don't understand what you're asking... The test will pass if the static UserController.screenAccess variable is 1 - and it looks like the Compare_Login method always sets it to 1.
This all looks fine, so if your test is failing, then there's something preventing the code from reaching that point.
For most unit test frameworks (I'm guessing you're just using the built in microsoft one?), exceptions are how unit test methods pass or fail - The Assert.Xyz methods throw an exception if the assertion isn't right, otherwise they don't. Any other exceptions that your code may throw also count as a fail.
The test framework catches any exceptions and flags the test as passed if there aren't any
I would guess that something in the Check_Login function or earlier in the Compare_Login function is throwing an exception. This is the only thing I can see that would cause your unit test to fail. I'm surprised however that you haven't noticed such an exception (try clicking on the failing unit test and seeing what details you can see about the failure)
I have a simple C# application/game using SFML.Net that currently stops running / terminates within 1 or 2 seconds after being executed without any warning, exception, etc. whatsoever. Consider the following code:
public static void Main(string[] args)
{
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(OnUnhandledException);
--> The following two lines are run
Console.WriteLine("Hello");
Console.WriteLine("Please don't go...");
// Run the game
try
{
--> This line is reached
Game.Run();
}
catch (Exception e)
{
--> This line is never reached
Console.WriteLine(e.Message.ToString());
}
--> These lines are never reached
Console.WriteLine("Noone ever comes here, I feel so lonely... :(");
Console.ReadKey();
}
}
At this point you probably expect that something is wrong with the Game.Run() method. The odd thing is that the first line of the method is never reached according to the VS Debugger.
public static void Run()
{
try
{
--> Never reached
LoadContent();
// Do stuff here
while (window.IsOpen())
{
// The classic game loop
}
}
catch (Exception e)
{
--> Never reached
Console.WriteLine(e.Message.ToString());
Console.ReadKey();
}
}
My guess is that either:
You are getting an Access Violation Exception which cannot be caught.
OR
There is some other exception before you go into the Run method that is not handled. In order to verify that, make sure your debugger stops on first chance exceptions.
It would also be helpful if you specify:
How do you know that the first line is never reached? breakpoint? output?
What happens when you expect this function to be entered? does your application exist?
Are you debugging step by step?
My Guess is that the exception is being thrown by another thread. You cannot catch an exception thrown from another thread in the main thread. So your breakpoint in catch will never be hit. Btw did you try having a breakpoint in your UnhandledExceptionEventHandler method OnUnhandledException? That is where all unhandled exceptions go! Hope this helps.
You can get all called functions stack in your application until the termination point with the Runtime Flow tool (30 day trial, developed by me) and find what actually happens.
I came back to this after a couple of months and realized how silly my mistake was. Apparently unmanaged code debugging wasn't enabled by default (this was my first time using VS2012), and this exception was being thrown from the base C++ libs of SFML.
For those who don't know, to enable unmanaged debugging:
Project > Properties > Debug > Select "Enable unmanaged code debugging"
I have a very simple application, we feed it a list of our websites, and it does a parallel foreach on them and inside each action it does an http post to it.
Similar to below:
static int success = 0
static void Main(string[] args) {
try {
Parallel.ForEach(sites, site=> {
try{
if(DoWebPost(site)) {
Console.Write("Posted {0} - {1}", ++success, site);
}
} catch {}
});
} catch {}
}
I can't figure out why it will throw an OutOfMemoryException, let alone why that will cause the entire application to crash, and not just catch and continue.
EDIT: Not exactly sure where the exception occurs, since it doesn't locally, only when running in production... meaning no debugging available. The Application is 64bits, and rarely uses more than 100 megs.
In the words of Marc Gravell
If you "fix" your code by handling this exception you are burying your head in the sand.
You mentioned the code that is posted is somewhat the same as the code you used.
Can you actually post the full code or the exact code that is causing this.
Something tells me you have some sort of memory leak, you need to address this first.