views:

249

answers:

5

I have something analogous to the following code snippets:

// file alpha.c
void function_A()
{
    int i;
    #include "code.h"
}

and

//file beta.c
void function_B()
{
    int i;
    #include "code.h"
}

and

// file code.h
for(i = 1;i < 10;i++)
{
    // do some stuff
    if (very_rare_event)
    {
        // do something else
    }
}

Yes, I am fully aware that its breaking all sorts of coding practices, but that's another story (its all part of a very large, very complex, very old system and its not going to be changed any time soon).

My question is this: Is it possible to set a breakpoint within code.h at the "// do something else" point, in a way that you can specify whether it is the instance of being included from alpha.c or beta.c? And if so, how?

A: 

Ok, I would like to tell you in lots of different ways why you need to change the system, but you've indicated that you are aware that this is not good and that it won't change so I'll try to refrain from doing that.

Could you perhaps do something along the lines of this:

// file alpha.c
void function_A()
{
    int i;
    const int foo = 1;
    #include "code.h"
}

and set a conditional breakpoint in code.h with the condition foo == 1 ? Do the same thing but set foo = 2 for function B to break there.

villintehaspam
A: 

Set a breakpoint in function_A or function_B, then Step Into the included code. You can then set a breakpoint where you need it.

This assumes that you've disabled most compiler and linker optimizations.

Adrian McCarthy
+2  A: 

Put #defines in the main files:

// file alpha.c
#define BREAK_FOR_ME 'A'
void function_A()
{
    int i;
    #include "code.h"
}

// file beta.c
#define BREAK_FOR_ME 'B'
void function_B()
{
    int i;
    #include "code.h"
}

Then in code.h:

// file code.h
for(i = 1;i < 10;i++)
{
    // do some stuff
    if (very_rare_event)
    {

    #ifdef BREAK_FOR_ME
        switch (BREAK_FOR_ME)
        {
        case 'A':
            // set breakpoint here...
            break;

        case 'B':
            // or here...
            break;
        }
    #endif

        // do something else
    }
}
egrunin
Clearly great minds think alike!
me_and
+1 Cunning switch use. Likely to get compiler warnings due to constant switch expressions, but if you're writing code with includes like this, I think compiler warnings are likely to be the least of your worries.
me_and
This might be OK when only a few files are involved and you don't want to change or add breakpoint locations too often. But it doesn't scale too well - too much of this, and you're probably approaching the level of effort it would be to just fix the oddball coding practices.
Michael Burr
A: 

Use #defines in your .c files, and #ifdefs in the .h file. Put some non-operation (perhaps increment then decrement a counter) inside the #ifdef, and set your breakpoint there. Note that you need to have some operation in there, as you can only set a breakpoint on an actual operation.

So:

// file alpha.c
#define FILE_ALPHA
void function_A()
{
    int i;
    #include "code.h"
}
#undef FILE_ALPHA

//file beta.c
#define FILE_BETA
void function_B()
{
    int i;
    #include "code.h"
}
#undef FILE_BETA

// file code.h
for(i = 1;i < 10;i++)
{
    // do some stuff
    if (very_rare_event)
    {
        // do something else
        #if defined FILE_ALPHA
            i++; //Set breakpoint here...
            i--;
        #elif defined FILE_BETA
            i++; //...or here...
            i--;
        #else
            i++; //...or here.
            i--;
        #endif
    }
}
me_and
Whoa, synchronicity :)
egrunin
A: 

Since something like this is probably needed only rarely, it probably wouldn't pay to figure out how to do it at the C source level or to jump through a bunch of hoops.

So, I'd probably just look at the disassembly for the function I wanted to break in and set the breakpoint at the assembly level.

As an experiment, I set a breakpoint on the line in code.h normally, and the debugger's Breakpoint window showed up with a tree of breakpoints:

o  code.h, line 9
|
+-- o   code.h, line 9
|
+-- o   code.h, line 9

Each entry could be disabled. There was no easy way to figure out which one corresponded to function_A() and which was for function_B() just by looking - I had to run the program with both enabled, and turn off the one I wasn't interested in when it was first hit. Not a great usability experience, but not too surprising given how rare the situation probably is.

If you need to do this more regularly, Visual C/C++ is supposed to let you fully specify a breakpoint using a "Context Operator":

{[function],[source],[module] } location

but I haven't been able to figure out how to actually use this syntax in the debugger IDE. If anyone has details, I'd appreciate a comment.

WinDBG in the Debugging tools for Windows also supports this syntax (or something very similar), but I can't verify exactly how (or if) it works at the moment).

Michael Burr