views:

77

answers:

4

We're getting some funny behavior in the Visual Studio debugger with the following. I'm not sure if it's the code or some debugger weirdness (seen stuff like it before). We are trying to return a pointer to an value in an array.

The weird behavior is that the value of x changes to equal y after func() is called a second time...at least, that's what it appears in the debugger.

I suppose my question is, is this even legal/safe?
The pointers should be on the heap in main()'s scope right, so it should be fine?

char stuff[100];

char * func()
{
    // i is random in the range
    stuff[i] = 'a';

    return &stuff[i];
}

main()
{
    char * x = func();
    char * y = func();
}
+1  A: 

You are returning pointers into the same container. Both x and y are pointers into elements of array. Any change that is performed in array will be visible through both pointers as they refer to the same region of memory.

If you need different results you will have to dynamically allocate new objects (whether explictly or implicitly with the use of std::string or std::vector --recommended).

David Rodríguez - dribeas
David Rodríguez - dribeas
You're still right, even with the random `i`. My first reading was that he was seeing `x == y` (pointers being identical), but on thinking about it he probably means that the strings they point to end up receiving identical changes, which is where you answer is correct.
Tyler McHenry
@David: Even though both pointers are pointing to the same array ("region"), it does not mean that the change is visible through both pointers. The function only changes a *single element* of the array, not the whole array. And even if they happen to change the same element, the content would not change in the second call since the value written is the same, 'a'.
PauliL
@PauliL: You are somehow right, in that there are different situations where the second call would not change the perceived state of the first call. In particular if `i1 <= i2` the second call would not affect the visible state of the first call. Nevertheless, the question is stating that he is seeing the change produced by the second call in the first one. So either it is for this reason or else I am lost: do you have any better explanation?
David Rodríguez - dribeas
@David: I don't understand what you mean with "i1 <= i2". The contents pointed by x is changed only if i has *the same value* in both calls (changes are 1:100) **and** the value written is different. But since the value written is always 'a', there can not be change in the contents pointed by x. I believe OP means that it is the *pointer* (address) that changes. The possible cause is given in Mike Seymours answer.
PauliL
@PauliL: In the general case (not interpreting as a string), the memory after the pointer it will affect in all `i1 <= i2`, interpreting it as a string, and even if the value set is the same, when `i1 = i2-1` there will be a visible change. The string will be seen as "aa", instead of "a" (and this is even worse if `i1==98` and `i2=99`, because that will produce an overflow when the returned pointer is interpreted as a string. But this discussion is going well beyond any interest to the actual question.
David Rodríguez - dribeas
A: 

The value of the pointer (the memory address) of x is not changing. The memory which x is pointing to is being modified.

tster
A: 

The entire program has undefined behavior because i is uninitialized. There's nothing else to explain. You're lucky it didn't decide to format your hard drive instead.

R..
The comment indicates that i is set at random. This is not the actual code. It was removed for brevity.
CrypticPrime
+2  A: 

Are you debugging with a debug build? You often get surprising results like this if you debug a release build.

A debug build will force the compiler to put all variables on the stack, and keep them around for their entire scope, so you get the expected debug view. A release build might reuse the space for one variable once it's never going to be used again, even if it is still in scope, and might keep short-lived variables in processor registers rather than on the stack.

In a release build, it's likely that x and y are placed at the same memory location (or register), since their usage lifetimes don't overlap. There's no need to keep x around after first line, so the compiler is allowed to discard it. If you were to use x later on in the function, then it would need its own space on the stack, so you would probably see it in the debugger as expected.

And to answer your question: yes this is valid and correct, as long as i is indeed in range.

Mike Seymour
I think this is the correct answer. If x and y are allocated in a register (or perhaps even in stack), the compiler may re-use the same register for y since x is no more needed. If the variables are displayed for example in the watch window, they will naturally show the same value. However, a good debugger would indicate which variables are currently not valid (perhaps by using different color).
PauliL