I have a rather strange problem that is occurring.
This is my code:
private async Task BreakExpectedLogic()
{
bool test = false;
if (test == true)
{
Console.WriteLine("Hello!");
throw new Exception("BAD HASH!");
}
}
Seems really simple, it shouldn't hit the Console.WriteLine or the throw.
For some reason it's always hitting the throw.
If I move the throw into its own method then it works fine. My question is how is it ignoring the if block and hitting the throw new Exception:
EDIT 1: I've updated my code to include the signature, I've removed everything not related to this problem and ran it, it still happens.
It seems to be the bug in async method, the code is not actually executed but debugger steps to the line with throw statement. If there are some lines of code before throw statement inside if these lines are ignored, debugger steps only to the line with throw statement.
Also, if you don't use variable - if (false) or if (true == false) then debugger steps to the correct line of code - to the closing curly brace.
This bug has been posted by #Matthew Watson to Visual Studio team (link is not available now).
Also, see similar question - Condition check in async method
EDIT (2017-10-06):
Issue cannot be reproduced in VS 2017 15.3.5 using .Net Framework 4.7. Seems like VS team has fixed this issue.
Just an addendum to the answer, I've recently encountered the same issue, and looked to the actual x86 code in the debugger, and it was generated in a weird way like this (simplified):
// if (...) {
0001: jne 0006
...
0006: jmp 0007
// }
0007: ret
So instead of directly jumping to the last instructions of the method, it does double jump, where I believe the second unconditional jump is mistakenly recognized as a part of the code inside if block.
So I would speculate that this bug might be related to JIT compiler.
Related
When I stepped over breakpoints in my code I have encountered strange behaviour of debugger:
public async Task DoSomeWork()
{
await Task.Run(() => { Thread.Sleep(1000); });
var test = false;
if (test)
{
throw new Exception("Im in IF body!");
}
}
Debugger goes into if body. It's remarkable that the exception is not really thrown but just looks like it is. So you can't reproduce that if you place breakpoint right on throw. You must place it above and step down to the if body to catch it. The same works on any kind of exception instance (as well as explicit null) and even on return instead of throw.
Besides that it works even if I remove line with await.
I tried to run this code snippet from different PCs so its not a PC trouble. Also I have thought it is bug in VS code and tried to run it in Rider from JetBrains - the same result.
I'm sure it's the async thing but how it explicitly works?
Your code reproduces the issue easily, in a "Debug" build, using Visual Studio 2015. I had only to add in Program.Main(), with a call to DoSomeWork().Wait();, set a breakpoint in the method and step through it.
As for why it happens, this is undoubtedly due to the combination of the async method being rewritten and the debugging database (.pdb) generated. Similar to iterator methods, adding async to the method causes the compiler to change your method into a state machine. The actual IL that's generated looks only a little bit like the original method. That is, if you look at it, you can identify the key components of the original code, but it's now in a big switch statement that handles what happens as the method returns at each await statement, and then is re-entered with the completion of each awaited expression.
When the program statement appears to be on the throw, it's really at the implicit return statement in the method. It's just that the debugging database for the executable doesn't provide a program statement for that line.
There's a hint, when debugging, that that's what's happening. When you step over the if statement, you'll notice it goes straight to the throw statement. If the if statement block were really being entered, the next program statement line would actually be the opening brace for the block, not the program statement.
You can also add e.g. a Console.WriteLine() at the end of the method, and that will give the debugger enough information to sync up and not show you at the wrong line number.
For additional information on how async methods are handled by the compiler, see Is the new C# async feature implemented strictly in the compiler, and the links provided there (including Jon's series of articles on the topic).
I am trying to test some code and now visual studio is throwing a null reference exception on the following line:
List<int> liveIds = new List<int>();
I am starting to think that visual studio has old code that it is looking at because no matter how I have tried to declare this line it continues to throw a null reference exception on this line.
Anyone know something that I might be missing?
UPDATE:
ok so I changed out the variable and now I can't get the same error to happen on the previous line. Now it is happening on this line.
Ok so after some testing, things worked once I refactored the code and extracted the following code to a new method:
// remove hospitals that are not currently assigned to someone
hospitalsToCheck.RemoveAll(
h =>
{
return
!currentAssignments.Exists(
a => a.AssignmentGroup.AssignedUnitIds.Intersect(h.Units.Select(u => u.UnitId)).Any());
});
It seems that when I had code that was manipulating the list in the same method that it was defined, that is when I was getting the null reference exception.
Maybe the debugger itself is producing the exception.
I got a very similar situation, where i'm assigning a value from a function and the exception occurs right after executing the function (the Locals window indicates that the function does return a value):
var xmlElement = Serialize(data);
From Disassembly it seems that the exception happens immediately after the assignment, but before the next line of code. I'm guessing this is where some debugger code gets executed:
Screenshot of disassembly
Maybe debugger did not expect for that line of code to be executed, because I altered the execution path with "Set Next Statement" command (moved from the "else" block into this one). Same thing happens if I alter the code (remove the "if") while the debug is running, but the problem does not repeat if I rerun the encompassing procedure after the edit.
I am using PostSharp in C#, for using AOP in my codebase. Recently i've noticed that errors are not being thrown where they are actually thrown, but at the end of the method which was weaved with any aspect. For example, take the sample code below:
public void methodUsingAspects()
{
doSomething1();
doSomethingWhichThrowsError(); //an error is thrown in this method
doSomething2();
} //in visual studio, while debugging, the debugger stops at this line (end of method), not at the actual line the error got thrown.
The error gets shown as if thrown where there is the last curly bracket }. This is quite frustrating especially when the error is thrown quite deep inside the calls the method does.
I can assume why this is done, since the code is changed - but is it possible to somehow leave it work as it was before?
There are multiple questions (1,2,3,4 etc. etc.) called "Why isn't this exception caught". Sadly, none of these solutions work for me... So I am stuck with a truly uncatchable exception.
I have a piece of code (.NET 4.0) that checks a large textfile for digits and numbers. Whilst testing I got a runtime exception:
What you see here is a try-catch pattern with a catchblock for an ArgumentOutOfRangeException. But during runtime, the try block throws an ArgumentOutOfRangeException that is not being caught.
I read the C# language specification section about the try-catch structure, and it says:
A catch block of a try statement is reachable if the try statement is reachable.
So in theory the above code should catch the exception.
Then I thought it might had something to do with the fact that this code is running in a task (during the processing of the textfile I also want to update the UI so I do it asynchronous). I searched around and then I found this answer by Jon Skeet. Basically suggesting I use Task.Wait in a try-catch block to catch any exceptions.
The problem I am facing now is that I can't really call Task.Wait because that would block the calling thread which is my UI thread! Then I figured that I could create an extra tasklayer to wait for that task:
//Code called from the UI
System.Threading.Tasks.Task.Factory.StartNew(()=>
{
//Create a new task and use this task to catch any exceptions
System.Threading.Tasks.Task task = System.Threading.Tasks.Task.Factory.StartNew(MethodWithException);
try
{
task.Wait();
}
catch(Exception)
{
MessageBox.Show("Caught it!");
}
});
But this still gives the same result... Then I thought that it could be because of the fact I am not specific enough with my Exceptiontype. But the C# Language Specification states:
Some programming languages may support exceptions that are not representable as an object derived from System.Exception, although such exceptions could never be generated by C# code.
So unless you use some sketchy third party API you're always good when you use Exception. So I found myself with an suggested answer by Jon Skeet that didn't quite work for me. That's when I knew I should just stop trying...
So does anyone know what is going on? And how can I fix this? I know I could just check if i is equal or bigger than text.Length but understanding what's happening is more important than working code.
This is simply an artifact of the debugger.
In the Debug menu, there's an option called Exceptions... Click it, and make sure to uncheck the "Thrown" checkbox here:
Many times, you'll want to see the error in context, even if it's inside a try/catch, which is what this setting is for. In this case, that is exactly what you ought to be doing, so that you can see compare i to the length of text and see where your problem is.
If you ran the code without the debugger (such as by double-clicking the executable or using the "Start without Debugging" option), you would "correctly" throw away the error without any alerts.
I just wrote the following test:
[TestMethod]
public void ArgumentOutOfRangeExceptionTest()
{
string test = "abc";
int i = 0;
try
{
while (true)
{
test.ElementAt(i);
i++;
}
}
catch (ArgumentOutOfRangeException)
{ }
}
It is working fine. I believe that you had another exception, which is not called in your calling code.
There is only one exception I know which can't be caught. It's the StackOverflowException. See this question about it.
I must be going out of my mind, because my unit tests are failing because the following code is throwing a null ref exception:
int pid = 0;
if (parentCategory != null)
{
Console.WriteLine(parentCategory.Id);
pid = parentCategory.Id;
}
The line that's throwing it is:
pid = parentCategory.Id;
The console.writeline is just to debug in the NUnit GUI, but that outputs a valid int.
Edit: It's single-threaded so it can't be assigned to null from some other thread, and the fact the the Console.WriteLine successfully prints out the value shows that it shouldn't throw.
Edit: Relevant snippets of the Category class:
public class Category
{
private readonly int id;
public Category(Category parent, int id)
{
Parent = parent;
parent.PerformIfNotNull(() => parent.subcategories.AddIfNew(this));
Name = string.Empty;
this.id = id;
}
public int Id
{
get { return id; }
}
}
Well if anyone wants to look at the full code, it's on Google Code at http://code.google.com/p/chefbook/source/checkout
I think I'm going to try rebooting the computer... I've seen pretty weird things fixed by a reboot. Will update after reboot.
Update: Mystery solved. Looks like NUnit shows the error line as the last successfully executed statement... Copy/pasted test into new console app and ran in VS showed that it was the line after the if statement block (not shown) that contained a null ref. Thanks for all the ideas everyone. +1 to everyone that answered.
Based on all the info so far, I think either "the line that's throwing is" is wrong (what makes you think that), or possibly your 'sources' are out of sync with your built assemblies.
This looks impossible, so some 'taken for granted assumption' is wrong, and it's probably the assumption that "the source code you're looking at matches the process you're debugging".
When things look right on the surface then it's likely something you would dismiss. Are you 350% positive that your DLL/PDB matches your source code thus giving you the right line?
Try manually deleting your assemblies and run whatever it is you're running. Does it fail as it should?
Try cleaning out your solution and recompiling. Copy the assemblies to wherever and run it again. Does it work this time? Null ref at the same spot?
Debug the surrounding lines for values you expect. parentCategory, etc. should match what you think.
Modify the code by throwing an exception. Do the stack trace lines match exactly the lines in your code?
I've had some extremely mind-boggling experiences just like this because one of my assumptions was wrong. Typical is a stale assembly. Question all assumptions.
What doesn't make sense, though, is that the OP states that the console.writeline outputs a valid int and it calls the same property as the line where he states the error is being thrown.
A stacktrace would be helpful, or being able to look at the actual unit test.
Yes, could we see the code of the category class .. in particular the Id property? Assuming the Id property is an int (and not a nullable int), the get method must be accessing a NULL object.
Id could be a nullable int type (int?) with no value, however I feel that the property Id must be doing more than just returning an int, and something inside that is null.
EDIT Your edit reveals this is more than peculiar, could you supply us with a stack trace?
I'm not an expert on C#, and am not sure if it makes a difference, but are you debugging in Debug mode, or Release mode? If you're in release mode, the line that your IDE is pointing to and the line the problem is actually on may be different (I know this is the case in C++ when using Visual Studio)
I'd have to agree with Brian... Maybe you're using outdated .pdbs and the code you're seen on debug mode does not comply with the code actually being debugged.
Try cleaning the project, and rebuilding it in debug mode.
Looks like NUnit shows the error line as the last successfully executed statement... Copy/pasted test into new console app and ran in VS showed that it was the line after the if statement block (not shown) that contained a null ref. Thanks for all the ideas everyone. +1 to everyone that answered.