[.net] Find out method's caller

Started by
10 comments, last by Washu 18 years, 1 month ago
Is it possible to find out a method's caller at runtime, or does any other way exist, which allows to examine the call stack at runtime? Since this thread is posted in the .NET section, suppose it is about .NET ;-)
Advertisement
System.Diagnostics.StackTrace is your friend.
However this does not work reliably of course due to the JIT performing inlining and other operations. ( you will get methods not showing up in the stacktrace that have been inlined but still exist in your source code )
Thanks for your help.
After trying out and looking into the documentation i found out, that it only works correctly with debug builds (well, of course it works correctly with release builds, too, but it does not work the way i expected ;-))
Thanks again, but i need to find another way.
Quote:Original post by Gluber
However this does not work reliably of course due to the JIT performing inlining and other operations. ( you will get methods not showing up in the stacktrace that have been inlined but still exist in your source code )

These limitations apply to any method you'd use that are built into the .NET Framework, though. It's good to be aware of the limitations, yes, but it should be noted that those limitations are part of the Framework and not the language or the StackTrace() class. (You could also disable optimizations, although this isn't something I could imagine being that important.)

Sample code for the curious:
StackTrace st = new StackTrace();StackFrame sf = st.GetFrame(0);Console.WriteLine("{0}", sf.GetMethod());
You might find the System.Reflection namespace useful. You can get the name of the currently executing method using the MethodInfo.GetCurrentMethod() static function.
MethodInfo mi = (MethodInfo) MethodInfo.GetCurrentMethod();Console.WriteLine("{0}", mi.Name);
If you execute the above inside a constructor you'll have to use ConstructorInfo in place of MethodInfo.

Using the above method you could set a static member to the currently executing method, accessed by whichever component you want. (If you're threading you'll need to create a static array, of course.) However, that system causes a runtime performance penalty whereas the StackTrace method only causes a penalty when it is needed or invoked.

I've used the StackTrace method as part of a logging class and never had an issue with it. Generally if a method is going to be inlined or optimized to the point of losing its identity that method isn't large enough to be the cause of a lot of problems. Even if it would be I don't think it'd be difficult to find.
..what we do will echo throughout eternity..
My problem is not the limitation of the framework, but the missing debug symbols

The following source

class Program{    static void X()    {        Y();    }    static void Y()    {        Z();    }    static void Z()    {        System.Diagnostics.StackTrace st = new System.Diagnostics.StackTrace();        Console.WriteLine(st);    }    static void Main(string[] args)    {        X();    }}


results in the following output with debug build:

at test.Program.Z()
at test.Program.Y()
at test.Program.X()
at test.Program.Main(String[] args)
at System.AppDomain.nExecuteAssembly(Assembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()

while the release build results in:

at test.Program.Z()
at test.Program.Main(String[] args)


missing the X and Y static methods
Quote:Original post by Talonius
You might find the System.Reflection namespace useful. You can get the name of the currently executing method using the MethodInfo.GetCurrentMethod() static function.
MethodInfo mi = (MethodInfo) MethodInfo.GetCurrentMethod();Console.WriteLine("{0}", mi.Name);
If you execute the above inside a constructor you'll have to use ConstructorInfo in place of MethodInfo.

No, you don't. ConstructorInfo and MethodInfo both inherit from MethodBase, which inherits from MemberInfo. MemberInfo is the class that contains the Name property, MethodBase is the class that contains the GetCurrentMethod() function.
MethodBase currentMethod = MethodBase.GetCurrentMethod();Console.WriteLine("{0}", currentMethod.Name);

Quote:Original post by Dope-Show
missing the X and Y static methods

As to be expected, since your static methods don't DO anything at all except delegate to the next static method.

In time the project grows, the ignorance of its devs it shows, with many a convoluted function, it plunges into deep compunction, the price of failure is high, Washu's mirth is nigh.

Oh, right, they are optimized away by the compiler i suppose.
But after adding Console.WriteLine("test"), they still didn't show up in the StackTrace.
Adding for(int i = 0; i < 10; i++) makes them show up.

So now the Question is, what operations does the compiler optimize away, and which don't.
I don't know, but anything not involving any declaration of local variables would be a good bet, since that doesn't need the function's scope to work.
Quote:Original post by Washu
No, you don't. ConstructorInfo and MethodInfo both inherit from MethodBase, which inherits from MemberInfo. MemberInfo is the class that contains the Name property, MethodBase is the class that contains the GetCurrentMethod() function.
Meh, I prefer to work at the most defined level, sorry. :)
Quote:Original post by Dope-Show
So now the Question is, what operations does the compiler optimize away, and which don't.
My understanding is that the compiler doesn't do most of the optimizations, the JITter handles most of that. Constants are inlined, some methods may be unrolled, etc. Some of the optimizations are discussed in this MSDN article.

I don't think you can ever count on being able to know what optimizations might be done. There are multiple host Frameworks around now, each a little different than the other.
..what we do will echo throughout eternity..
Quote:Original post by Bob Janova
I don't know, but anything not involving any declaration of local variables would be a good bet, since that doesn't need the function's scope to work.


I tested it, but no difference

Quote:Original post by Talonius
My understanding is that the compiler doesn't do most of the optimizations, the JITter handles most of that.


Well, the JITter is also a compiler, a Just-In-Time Compiler, but that doesn't matter, does it? [wink]

So is there a way to find out a method's caller, that actually works and is reliable?

[Edited by - Dope-Show on March 17, 2006 2:02:28 PM]

This topic is closed to new replies.

Advertisement