Can a .NET stack trace be generated that excludes internal methods? - c#

Sometimes when an exception happens on a .NET class method, that method itself internally is calling a bunch of other methods but the error happens inside one of those. This makes for a bloated and messy stack trace with more "meaningless" stuff than needed. Is there a way to get a stack trace that stops at the public .NET method that caused the error vs having it show all the internals of the .NET methods?
An example of this would be ADO.NET's ExecuteNonQuery(). Internally that calls like 5-6 functions and the exception may not happen until that 6th nested function and so the stack trace shows all of those internals which we can't do anything about or care about. It would be nice and cleaner if it stopped at ExecuteNonQuery() since that's the public facing .NET method.

The short answer is "no", you can't change the way .NET generates stack traces. When a stack trace is generated, it shows every call site. However, if you want to have some custom behaviors, you can write some custom code to edit the output of a stack trace you generate.
To generate a stack trace, you use code like this:
StackTrace stackTrace = new StackTrace();
StackFrame[] stackFrames = stackTrace.GetFrames();
The constructor will generate the stacktrace data, and .GetFrames() will return the methods to you. From that point, you can filter them as you wish (use stackFrame.GetMethod() to get the method info for each frame -- either to filter it or to add it to a StringBuilder for your string output, etc)
Reference: https://msdn.microsoft.com/en-us/library/system.diagnostics.stacktrace(v=vs.110).aspx

Related

Why does this recursive method cause a Stack Overflow error when it has no variables?

I have recursive method like this, which doesn't contain any variable. Why is it throwing a stack overflow exception?
class MainClass
{
static void Main() => Bark();
static void Bark() { Bark(); }
}
in the example above, I did not create any variables. If I create any variable(either as a parameter or inside a method), then this is understandable: many variables have been created in the thread's stack, and due to the lack of memory, I get an error.
I don't understand, is the method itself is also stored on the stack? Why am I getting the error?
The stack frame does not just contain parameters, it also contains a return address, so that the processor knows where to go back to.
Furthermore, the hidden this pointer is also a parameter. To remove that you would need a static function.
There is also the ebp or other stack-frame pointer, which can be pushed onto the stack for each call, depending on the exact calling convention.
So whatever you do, you will definitely get a stack overflow at some point, unless the compiler decides to perform tail-recursion.
If you were to debug this piece of code and look at the "call stack" window then you would see it attempt to add Bark to the call stack an infinite amount of times because the recursion has no end point.
I believe what you're expecting to see is tail recursion. Unfortunately C# compiler doesn't support it.

Push a stack onto another stack

In C#, is there a way to push one Stack onto another Stack without iterating through the stack elements? If not, is there a better data structure I should be using? In Java you can do:
stack1.addAll(stack2)
I was hoping to find the C# analogue...
0. Safe Solution - Extension Method
public static class Util {
public static void AddAll<T>(this Stack<T> stack1, Stack<T> stack2) {
T[] arr = new T[stack2.Count];
stack2.CopyTo(arr, 0);
for (int i = arr.Length - 1; i >= 0; i--) {
stack1.Push(arr[i]);
}
}
}
Probably the best is to create an extension method. Note that I am putting the first stack "on top" of the other stack so to speak by looping from arr.Length-1 to 0. So this code:
Stack<int> x = new Stack<int>();
x.Push(1);
x.Push(2);
Stack<int> y = new Stack<int>();
y.Push(3);
y.Push(4);
x.AddAll(y);
Will result in x being: 4,3,2,1. Which is what you would expect if you push 1,2,3,4. Of course, if you were to loop through your second stack and actually pop elements and then push those to the first stack, you would end up with 1,2,4,3. Again, modify the for loop as you see fit. Or you could add another parameter to specify which behavior you would like. I don't have Java handy, so I don't know what they do.
Having said that, you could do this, but I don't make any guarantees that it will continue to work. MS could always change the default behavior of how stack works when calling ToList. But, this is shorter, and on my machine with .NET 4.5 works the same as the extension method above:
1 Line Linq solution:
y.Reverse().ToList().ForEach(item => x.Push(item));
In your question, wanting to do this "without iterating through the stack elements" basically means a LinkedList-based stack where you would just join the first and last elements to combine stacks in constant time.
However, unless you've a very specific reason for using LinkedList, it's likely a better idea to just iterate over an array-based (List-based) stack elements.
As far as a specific implementation goes, you should probably clarify whether you want the second stack to be added to the first in the same stack order or to be reversed into the first stack by being popped out.
An addAll would just be a convenience method for a foreach loop that adds all of the items. There really isn't much you can do besides that:
foreach(var item in stack2)
stack1.Push(item);
If you do it particularly frequently you can add an extension method for it, for your own convenience.
This isn't meant to be done with the current .NET Stack implementation.
In order for the content of a Stack to be "grafted" onto the end of another Stack without iterating though its elements internal implementation details how the Stack class stores them in memory has to be known. Based on the principle of encapsulation this information is "officially" only know inside the Stack class itself. .NET's Stack does not expose methods to do this, so without using reflection there is no way to do it as the OP requested.
Conceivably you could use reflection to append to the internal array of one Stack the content of another Stack and also update the field that stores the stack length but this would be highly dependent on the implementation of the Stack class which could be changed in future versions of the framework without warning.
If you really need a Stack that can do this you could write your own Stack class from scratch or simply use another collection like ArrayList or LinkedList which have the method you want and add Push and Pop extension methods to them.

Is it possible to delete or insert frames into the C# call stack?

Using StackTrace I can get the stack frames. My question is whether it is possible to manipulate the call stack in C#? More specifically: Is it possible...
to insert a frame into the call stack? or
to delete a frame from it?
Stack is a very internal component of program's runtime. Having the ability to alter it would make it possible to:
Make almost unrestricted goto's. Something that is considered a very bad programming practice and is not possible even in PHP. Debugging such thing would be a complete mess.
Inject code on method returns. This may be useful, but is already covered by aspect oriented tools, like PostSharp or Spring.NET, which allow you to do this in clean and predictable way. And they cover much more cases than just method returns.
Thus, I do not think there is any programming language that allows you to manipulate stack explicitly. It would make things very messy and any benefits it may produce are already covered by Aspect-Oriented-Programming. I bet AOP will make you able to achieve what you want.
It is easy to manipulate the stack in Smalltalk, but I don't think it is possible in C#.
StackTrace class doesn't support this kind of manipulation. Frames are read only as per msdn (only GetFrame, GetFrames methods are available).
To see how the class is created by framework you can have a look directly into source code of the class.
No, it is not possible. The Stack Is An Implementation Detail.
Moreover, the ability to manipulate the stack will bring a LOT of security/consistency issues. This is why manipulating the stack is a bad practice/a security bug even when you can do it (in C, for example). For example,the infamous "buffer overflow" category of security issues spring exactly from this: the ability to insert a "goto", a new stack frame, into the code, so that upon return a malicious payload is executed instead of the legitimate calling function.
But then, why would you like to do it? Given a real goal, we could better reason how to do that, and suggest good alternatives
Yes, you can via Reflection.
Ultimately it's a string.
The following is an exception class for logging Javascript exceptions with the javascript stacktrace as a C# exception, preserving the original stack trace.
using System.Reflection;
public class JsException : Exception
{
static readonly FieldInfo _stackTraceString = typeof(Exception).GetField("_stackTraceString", BindingFlags.GetField | BindingFlags.NonPublic | BindingFlags.Instance);
public JsException(string error, string stack)
: base(error)
{
_stackTraceString.SetValue(this, stack);
}
}

Print Stack Trace in Output Window

C#, WinForms: Is there a way I can see which methods are calling a specific method? well I can put a break point and see the call stack, but this one is UI related and it is a DoubleClick event, so I thought it will be helpful if something similar to Debug.Writeline(....) can also print call stack on a method so I could write it at the beginning of my method and see ok this time it is cvalled from this method, this time from that method, etc...
Use the Environment.StackTrace property.
What you are looking for is System.Diagnostics.StackTrace. You simply create a new instance at the point where you want to look at the stack.
Beware, though, that creating a stack trace is very expensive.

How to detect a bad way of re-throwing a C# Exception using StyleCop or VS2010?

My colleagues are seasoned C++ hackers switching to .Net. One of the mistakes that they make unintentionally is writing code like this:
catch(ArgumentExcepttion ae)
{
// Code here logs the exception message
// And this is supposed to re-throw the exeception
throw ae; // as opposed to throw;
// But, as we all know, doing this creates a new exception with a shorter stack trace.
}
I have seen this done in many many places. I cannot really think of a situation where cutting off the stack trace would be useful. I think that should be exceptional situation that deserves a comment. Correct me if I am wrong. If the stack trace is to be cut, I think it is always better to do:
throw new ArgumentException("text", ae /* inner exc */);
Anyhow, what I want to do is detect all such cases and give a warning. A regular expression search is of no help, because of this:
catch(Exception e)
{
Exception newExc = new Exception("text", e);
Log(newExc);
throw newExc;
}
I would have to use a tool such as StyleCop (which I have, version 4.3.3.0 ). I am using VS2008 for now, but will be switching to VS2010 very soon.
Any thoughts on how to accomplish what I am looking for?
FxCop has a rule for this: RethrowToPreserveStackDetails
Once an exception is thrown, part of
the information it carries is the
stack trace. The stack trace is a list
of the method call hierarchy that
starts with the method that throws the
exception and ends with the method
that catches the exception. If an
exception is re-thrown by specifying
the exception in the throw statement,
the stack trace is restarted at the
current method and the list of method
calls between the original method that
threw the exception and the current
method is lost. To keep the original
stack trace information with the
exception, use the throw statement
without specifying the exception.
I believe FxCop Analysis is built in to VS2010 but I'm not 100% sure...
Here is the Microsoft download link for FxCop.
Is the code catching exceptions unnecessarily? If you are only interested in logging the exception, then you only need an catch at the top level of your code (at the last possible point where you can do the logging). This could seriously reduce the number of catches you have to worry about.
I would suggest to look for catch-blocks ending in a throw ...; instead of ending with throw;.
Although you get some false positive, you can filter them out by hand.

Categories