advanced Visual Studio kung-fu test -- Calling functions from the Immediate Window during debugging
Asked Answered
M

2

6

I see some related questions have been asked, but they're either too advanced for me to grasp or lacking a step-by-step guide from start to finish (most of them end up being insider talk of their own experiment results). OK here it is, given this simple program:

#include <stdio.h>
#include <string.h>

int main()
{
    FILE * f;
    char buffer[100];

    memset(buffer, 0, 100);

    fun();

    f = fopen("main.cpp", "r");
    fread(buffer, 1, 99, f);
    printf(buffer);
    fclose(f);

    return 0;
}

What it does is basically print itself (assume file name is main.cpp).

Question

How can I have it print another file, say foobar.txt without modifying the source code? It has something to do with running it through VS's, stepping through the functions and hijacking the FILE pointer right before fread() is called. No need to worry about leaking resources by calling fclose().

I tried the simple f = fopen("foobar.txt", "r") which gave

CXX0017: Error: symbol "fopen" not found

Any ideas?

Edit

I found out the solution accidentally on Debugging Mozilla on Windows FAQ. The correct command to put into the Immediate Window is

f = {,,MSVCR100D}fopen("foo.txt", "r")

However, it doesn't really answer this question:

  • I still don't understand what is going on here.
  • How to systematically find out the {,,MSVCR100D} part for any given method? I know the MSVCR version changes from system to system. How can I find that out?
  • Could anyone explain the curly brace syntax, especially, what are those two commas doing there? Are there more hidden gems using this syntax?
Mammal answered 10/6, 2010 at 4:47 Comment(0)
K
8

The curly-braces syntax is the VS Context Operator, which is mostly broken - as elaborated at the link (or at least, hardly a hidden gem). It is used anywhere the VS expression-evaluation-engine needs to resolve functions at runtime, e.g. evaluating compound expressions in the watch window, setting breakpoints, or (as you witnessed) in the immediate/command windows.

Its 3rd argument is the binary which includes the implementation of the function you wish to call. For a CRT function such as fopen, that usually amounts to -

MSVCR[VS version][D].dll

(I seem to recall the extension was needed - but maybe that changed in VS2010). The 'D' indicates the debug dll version. The VS version number is decoded as: VS2005 -> 8, VS2008 -> 9, VS2010 -> 10.

Also note the evaluation-engine has various other gotchas to watch out for.

Koffman answered 13/6, 2010 at 12:50 Comment(2)
That's an extremely detailed write-up. I wish I could upvote 10 times! Just curious: how did you get to learn about this obscure thingie? Your blog came out second on Google for "visual C++ context operator". Personally, I think this is an extremely useful feature. I just don't know why it isn't more advertised or well polished.Mammal
Thanks - I was actually worried linking to my own blog would be perceived as vanity, but you really shouldn't trust MSDN here. These are just write-ups of my own experimentation, and are by no means official or even proven. If you (like me) like undocumented VS goodies, you'd find plenty more in the blog. This particular hidden feature probably wouldn't get any dev love anytime soon - there are some opinions on it in the comments.Koffman
M
4

To supplement Ofek's excellent answer, here is a way I found to systematically find out what module a function call belongs to. (i.e. the MSVCR100D part).

  • Step through the debugger looking for an instance of the function you want to call. (In this case, I was looking for fopen);
  • When you find it, step into it by pressing F11.
  • Right click and choose Show Disassembly
  • You can find the address of the currently executing instruction. (Click around the Viewing Options to toggle it if it isn't shown)
  • Open the Modules debug window (Alt+Ctrl+U)
  • Look through the list of loaded modules with the Address range covering the current instruction's address. Bam, you've found the module name for the function!

I believe you can use this method to find the module name for any class. This can be useful when for example you're reviewing a large code base and you want to invoke some arbitrary class's method on the fly in the Immediate Window. You can probably also create instances of classes on the fly by calling the constructor yourself.

Now wasn't C++ a native language? We almost feel like in a managed, scripting environment here :P

Mammal answered 13/6, 2010 at 14:37 Comment(2)
Don't you see the module name at the call stack itself (to the left of the function name)? I added a screenshot here - go2.wordpress.com/…Koffman
To raise that scripty touch one notch up, I ruthlessly use edit-and-continue. Thanks for a post idea..Koffman

© 2022 - 2024 — McMap. All rights reserved.