C/C++ Variable defined in scope gives error depending on scope

AI Thread Summary
The discussion revolves around a C++ code snippet where the variable scope and memory management are causing confusion. The code runs successfully when certain lines are commented out but fails otherwise, prompting questions about variable scope. The key issue is that the pointer variable "i" is defined within a limited scope due to the braces, making it inaccessible outside that scope. When "i" is reassigned to point to another variable, the original memory allocated with "new" becomes inaccessible, potentially leading to memory leaks if not properly managed with "delete." Participants emphasize the importance of pairing "new" with "delete" to avoid memory issues and caution against relying on compiler behavior regarding variable lifetimes. They also stress the need for clear communication when seeking help, suggesting that providing minimal code examples can clarify issues. The conversation highlights the complexities of memory management in C++, particularly the distinction between stack and heap allocation, and the significance of understanding scope rules to prevent errors.
member 428835
Hi PF!

The following runs if lines 5 and 11 are commented, but fails otherwise. Can someone explain what's happening here? Something with scope but I'm very lost. Thanks in advance!
C++:
#include <iostream>

int main()
{
    {
        int* i = new int;
        {
            int b = 5;
            i = &b;
        }
    }

    std::cout<< *i;
    return 0;
}
 
Technology news on Phys.org
Those {} brackets on lines 5 and 11 restrict the definition of "int* i = new int;" on line 6 to within that scope from 5 to 11. So *i is not defined on line 13.
You can also move line 6 to just beneath line 4 to increase the defined scope of *i to include the print statement on line 13. (In this case, that would make the nested {{ ...}} unnecessary, so you might just as well remove the lines that you mentioned.)
 
FactChecker said:
Those {} brackets on lines 5 and 11 restrict the definition of "int* i = new int;" on line 6 to within that scope from 5 to 11. So *i is not defined on line 13.
You can also move line 6 to just beneath line 4 to increase the defined scope of *i to include the print statement on line 13. (In this case, that would make the nested {{ ...}} unnecessary, so you might just as well remove the lines that you mentioned.)
Thanks. I thought the point of using "new" was to store on the heap, which I thought meant we had to manually allocate memory, so without deleting it was going to stay. Can you correct my misunderstanding?
 
1. The } means you told the compiler you didn't need the variable any more. Why are you surprised that it took you at your word?

2. Always always always pair news and deletes. Always. This will save you lots of time and trouble,

3. Multiple people have asked you multiple times to post the minimum code needed to demonstrate the problem. Had you done that, you would have discovered the problem with the braces. Maybe that would have pointed you at the problem, and maybe it wouldn't. But the idea that you want our help but don't want our advice i not going to get you where you want to go.

4. Do not count on anything implementation dependent, like what goes in what segments. In particular:
-- Do not count on the compiler preserving the value of a variable after you told it you don;t need it any more
-- Do not assume that the garbage collection will clean up after you when you are done with things

Tell the computer what you want it to do. Don't depend on it anticipating.
 
  • Like
Likes Grelbr42 and Filip Larsen
joshmccraney said:
I thought the point of using "new" was to store on the heap, which I thought meant we had to manually allocate memory, so without deleting it was going to stay.
You're confusing two different things.

The variable i in your code is not an int. It's a pointer to an int. It is only in scope inside the inner pair of braces. That's true regardless of how you assign the pointer.

The actual int variable is allocated by "new" and, since you did not include a corresponding "delete", it will either be automatically thrown away when your program exits, or become a memory leak, depending on the specific implementation. Assigning a pointer to that int to the pointer variable i, and what scope that pointer variable is visible in, has nothing whatever to do with any of that.
 
  • Like
Likes Grelbr42 and (deleted member)
joshmccraney said:
Thanks. I thought the point of using "new" was to store on the heap, which I thought meant we had to manually allocate memory, so without deleting it was going to stay. Can you correct my misunderstanding?
Trying to use "new" and "delete" to control how long memory is kept is making things much more complicated than they usually need to be. The usual scope rules are very good at automatically taking care of those things. You should use the scope rules in the methodical way they were intended until they are very natural for you.
 
FactChecker said:
Trying to use "new" and "delete" to control how long memory is kept is making things much more complicated than they usually need to be. T
For an int, I agre. And calling a non-integer variable "i" is also a dirty trick played on Future You.

But fort a big, complex object? I think new/delete is much more convenient taht malloc./sizeof/free. And if a problem with a big, complex object? also eppears when replaced by an int, it will help us figure out what is wrong.
 
  • Like
Likes FactChecker
Vanadium 50 said:
For an int, I agre. And calling a non-integer variable "i" is also a dirty trick played on Future You.

But fort a big, complex object? I think new/delete is much more convenient taht malloc./sizeof/free. And if a problem with a big, complex object? also eppears when replaced by an int, it will help us figure out what is wrong.
I agree that if customized memory management is needed, then it is nice.
Some situations where it is needed are where many (or an undetermined number of) objects need to be created and deleted during a single run in a single task. That is a key feature of Object Oriented Design (OOD).
My caution is that it should not be used when the simple scope rules suffice.
 
  • Like
Likes Vanadium 50
Vanadium 50 said:
But fort a big, complex object? I think new/delete is much more convenient taht malloc./sizeof/free.
But it's less convenient than just declaring the variable on the stack in the appropriate scope.
 
  • Like
Likes FactChecker
  • #10
PeterDonis said:
But it's less convenient than just declaring the variable on the stack in the appropriate scope.
And more treacherous.
 
  • #11
PeterDonis said:
than just declaring the variable on the stack
When you can/

An int? Sure. A variable number of objects of variable size? Not so easy. Ther'es a reason that the developers put in new/delete. I mean besides tripping up the unwary.
 
  • Like
Likes FactChecker
  • #12
Vanadium 50 said:
1. The } means you told the compiler you didn't need the variable any more. Why are you surprised that it took you at your word?

2. Always always always pair news and deletes. Always. This will save you lots of time and trouble,

3. Multiple people have asked you multiple times to post the minimum code needed to demonstrate the problem. Had you done that, you would have discovered the problem with the braces. Maybe that would have pointed you at the problem, and maybe it wouldn't. But the idea that you want our help but don't want our advice i not going to get you where you want to go.

4. Do not count on anything implementation dependent, like what goes in what segments. In particular:
-- Do not count on the compiler preserving the value of a variable after you told it you don;t need it any more
-- Do not assume that the garbage collection will clean up after you when you are done with things

Tell the computer what you want it to do. Don't depend on it anticipating.
dude i cant tell what you're talking about re comment 3. my OP WAS the min working code. i know there's an error, hence me saying "The following runs if lines 5 and 11 are commented, but fails otherwise". I literally spelled out what the issue was and how to get rid of it.

your constant berating is ridiculous. thanks to everyone, but after a decade im done with this site and will not recommend peers to it. thanks to all who have helped. so long pf!
 
  • #13
joshmccraney said:
The following runs if lines 5 and 11 are commented, but fails otherwise.
What does "fail" mean?

Did you get a compiler error message, or a run-time error message? If so, what?

Or did it compile and run without error messages, but produce unexpected output? If so, what output did you expect, and what did you actually get?
 
  • #14
Here's my understanding of what's happening with your code.

Line 6 allocates a pointer-to-int named i on the stack. The scope of i is lines 6 through 11. Line 6 also allocates an anonymous int on the heap, containing whatever "random" sequence of bits happened to be there already, and stores its address in i.

Line 8 allocates an int named b on the stack, and stores the value 5 in it.

Line 9 stores the address of b in i, overwriting the address of the anonymous int (from line 6), which is now inaccessible.

The closing brace in line 10 terminates the scope of the name b that was defined on line 8. You cannot use it past this point. What happens to the value 5 stored on the stack is undefined. It depends on the compiler and operating system. The value 5 might remain accessible via the pointer i, as *i, until its location is allocated to something else.

However...

The closing brace in line 11 terminates the scope of the name i that was defined on line 6. You cannot use it past this point.

Therefore I would expect line 13 to produce a compiler error message, something like "undefined name" or "undeclared variable". Is that what happened?
 

Similar threads

Replies
22
Views
3K
Replies
8
Views
2K
Replies
1
Views
1K
Replies
13
Views
2K
Replies
1
Views
1K
Back
Top