views:

90

answers:

4

I have a few simple lines of code (below). [bp] indicates a breakpoint.

     for(int i=0;i<300;i++){}
     int i=0;
     cout<<i;
[bp] for (i=0;i<200;i++){}

When I debug this in visual studio, it tells me that i is equal to 300 on the breakpoint. Annoyingly, 0 is printed to the console. Is there any way to make it realize that two variables in different scopes can actually have the same name?

I also want to add some code to the second loop and then debug it - but when I try to do that, i is consistently shown as 300. Very annoying.

+1  A: 

If your breakpoint is on the

for (i=0;i<200;i++){}

line, that means that the new i hasn't initialized yet when the breakpoint is hit, because that line of code hasn't executed yet. So it's still carrying the original i value.

Robert Harvey
The new `i` isn't initialized yet even though it was initialized after the first for loop, and before the breakpoint? Not sure I understand. Can you please expand on this?
Cam
But why isn't it using the `i` declared above the `cout`? Why is it using the value from the earlier loop?
Noon Silk
Good question. Almost looks like it's reusing the loop-scoped i, doesn't it?
Robert Harvey
@Robert Yeah, It's weird. But I've not done much C++. I just tested it, however, and it does happen. The second declaration is ignored (I don't get 0 printed, like he says he does). I suppose there is a reason, but I don't know it.
Noon Silk
So you've got three different i's in there. Do we even need to continue this conversation?
Robert Harvey
@Dave: That's pretty messed up, if it's true.
Robert Harvey
@Robert: The second `i` is initialized on line 2 and there are only 2 variables. Also, the scope of the first `i` is limited to the first for-statement in any *compliant* compiler.
Georg Fritzsche
Plus remember that it's _outputting_ as expected. Like I said in my question just the debugger was misbehaving.
Cam
+1  A: 

Brace for impact


The use of the same varibale for different perpose at different places in code is NOT ideal.

Here's the solution though:
Use braces to separate the different use-cases of the same variable.

for(int i=0;i<300;i++){}

{
     int i=0;
     cout<<i;
}

{
[bp] for (i=0;i<200;i++){}
}

NOTE:
As Robert rightly pointed out, unless the instruction is executed,
i will not be initialised to the new value.

GoodLUCK!!

CVS-2600Hertz
Ah. That makes sense. Edit: No it doesn't, actually. Can you explain why 0 was cout'd, but 300 was displayed by the debugger?
Cam
With that variation there is no variable `i` in scope for the second loop. Also, the variables are already scoped sufficiently in the OP, the scope of the first `i` is limited to the first for-statement... its just a debugger issue.
Georg Fritzsche
Also as keith says above, it might also be an issue with the debugger tooltip implementation...
CVS-2600Hertz
+4  A: 

in my visual studio, looking at the debugger Locals window

        i   300 int
        argc    1   int
        argv    0x00214b88  wchar_t * *
        i   0   int

NOTE! there are two i varibles in the debug output, i == 300 and i == 0

I'm thinking the reason its getting confused is a quirk/bug of the debugger where it tracks both i's then gets confused when you hover over an i, it just returns the first i? or some such, I don't think its semantically checking which i to show.

Keith Nicholas
Yup - incrediman has hit on a corner case that the debugger doesn't handle well. He may want to bug this on connect.microsoft.com.
Michael Burr
Weird - thanks. @Michael, will do!
Cam
A: 

The third i can alias the first i, because they have non-overlapping scopes. The second i cannot alias the third, because their scopes do overlap.

Hence, the compiler knows it needs to allocate storage for at least two integers. The space for the first integer can be shared by the first and third i, and the the space for the second i is reserved exclusively for the second i. These locations could be registers or stack slots, without loss of generality.

Interim conclusion: for the compiler, it doesn't matter how often you use the name i. It only cares how many variables you have, and how their scopes overlap.

So, when the debugger hits the second for-loop, it sees that you're watching the third i. The debugger looks up the location of the third i. Since that location was also used for the first i, it still contains 300. That of course doesn't matter for the program, as you start out by writing 0 to the third i, overwriting the old value 300 in that location.

So, the essential step is understanding how variables can be mapped to locations.

MSalters
What third `i`? There are only two declared.
Georg Fritzsche
There's an i in the first loop (declared), a second i between the for loops and a third one in the second for-loop. Perhaps I should have clarified more that the third `i` isn't declared in a C++ sense. It's a third variable when it comes to assignment of locations. This is the case because there's no dataflow dependence between them. Google for Static Single Assignment (SSA) for a more detailed explanation how a single name can map to two variables at compiler level. SSA takes the idea to an extreme (each variable is defined by a single unique write) but the concept is more general.
MSalters