[.net] Find out method's caller

Recommended Posts

Dope-Show    132
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 ;-)

Share on other sites
Gluber    122
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 )

Share on other sites
Dope-Show    132
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.

Share on other sites
Talonius    643
Quote:
 Original post by GluberHowever 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.

Share on other sites
Dope-Show    132
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.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)

while the release build results in:

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

missing the X and Y static methods

Share on other sites
Washu    7829
Quote:
 Original post by TaloniusYou 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-Showmissing 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.

Share on other sites
Dope-Show    132
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.

Share on other sites
Bob Janova    769
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.

Share on other sites
Talonius    643
Quote:
 Original post by WashuNo, 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-ShowSo 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.

Share on other sites
Dope-Show    132
Quote:
 Original post by Bob JanovaI 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 TaloniusMy 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]

Share on other sites
Talonius    643
Quote:
 Original post by Dope-ShowWell, 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?

Heh heh. Semantics!

The only way I can think of is to manually track the function name yourself ala the static variable. Everything else is subject to the whim of the system.

Washu might have some more ideas. He is DotNetGod! :)

Share on other sites
Washu    7829
Quote:
Original post by Talonius
Quote:
 Original post by WashuNo, 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. :)

That's silly. The more abstract the level you work on, the less you have to worry about implementation details. The less you have to worry about implementation details the faster your ability to test, develop and debug code.