Partager via


More caveats about #line

I posted here about how you can use #line in the C# compiler to associate C# code with some other source file than the one it was compiled with. This can be very useful for code generation and for "hiding" various parts of the function from the debugger.
"Josh" asked an interesting followup question here.

But what I really want to be able to do... is to insert something like
#lineNo and #methodName into C# code and have the compiler replace it with the current method name for instrumentation purposes. This would be much better than using reflection.
Maybe for Orcas?
 

I don't fully understand what he's asking, but it does bring up some interesting points.

First, you can give filename information as well as the line number, so you really can map to any random line in any random source file.  The syntax would be: #line 15 "MyFile.txt".

Second, recall that this #line stuff just changes how the sequence points (the IL to source mapping) in the pdb are written - it doesn't have any impact on the actual code generated or the metadata. Since the debugger uses the pdb to map from a function back to source, changing the pdb lets you have an arbitrary mapping here.

In constrast, a managed callstack uses metadata, and not PDB information, to get the function names. So the #line stuff won't affect the function name in the callstack.
So you can use #line to have it such that when you're stopped in function Foo(), it maps you to the source for function Bar(). However, the callstack will still be accurate and show that you're in function Foo().
You could name your new instrumented functions like Bar_Probe() instead of Foo(), and then use #line to map to file and line number for Bar()'s source. Then the callstack would be more intuitive. Compilers can use these sort of naming conventions to try and make their code more debuggable without changing codegen. (I recall observing anonymous delegates doing this)

Comments

  • Anonymous
    August 03, 2005
    The comment has been removed
  • Anonymous
    August 03, 2005
    I see. Like the C++ preprocessor's "LINE" and "FILE" macros? Yeah, I personally would like that too. It's true that you could have some pre-processing tool inject them for you (right before C# builds), but it's much nicer to have it in the language.
    It's true you can use the StackTrace class to get it at runtime (see http://sastools.com/b2/post/79394174 for example), but I agree that's a total pain and has problems.

    Note that this is purely a compiler issue. Other .Net compilers (such as MC++) have this functionality.
  • Anonymous
    August 03, 2005
    Hi Mike,

    Wow and thanks, wasn't expecting a reply... CN Got it just right though, it was actually something much simpler I was hoping for...

    public void SomeMethod()
    {
    Logger.LogEntyIntoMethod(#MethodName, #FileName);
    }

    Instead of maybe...

    public void SomeMethod()
    {
    Logger.LogEntryIntoMethod("SomeMethod", "someFile.cs");
    }

    I agree that this could be achieved using stacktraces or even reflection.GetCurrentMethod but that affects performance.

    Thanks anyway and sorry for sending you on a wild goose chase!
  • Anonymous
    August 24, 2005
    I wrote some C# sample code to get an ISymbolReader from a managed PDB (Program Database) file and then...
  • Anonymous
    May 27, 2007
    I mentioned in the recent dev lab that you can debug at the IL level . I demoed two ways to do this,