Variable defined in scope gives error depending on scope

  • Context: C/C++ 
  • Thread starter Thread starter member 428835
  • Start date Start date
  • Tags Tags
    Error Scope Variable
Click For Summary
SUMMARY

The forum discussion centers on the scope of variables in C++ and the implications of using dynamic memory allocation with the "new" operator. The user encountered an error when trying to access a pointer variable, "i", outside its defined scope, leading to confusion about memory management. Key insights include the necessity of pairing "new" with "delete" to avoid memory leaks and the importance of understanding variable scope to prevent errors. The discussion emphasizes that the compiler does not retain variable values once their scope ends, which is crucial for effective memory management.

PREREQUISITES
  • Understanding of C++ variable scope and lifetime
  • Familiarity with dynamic memory allocation using "new" and "delete"
  • Knowledge of stack vs. heap memory management
  • Basic debugging skills in C++ to interpret compiler error messages
NEXT STEPS
  • Research C++ variable scope rules and their impact on memory management
  • Learn about memory leaks and how to prevent them in C++ applications
  • Explore best practices for using "new" and "delete" in C++
  • Investigate the differences between stack and heap memory allocation
USEFUL FOR

C++ developers, software engineers, and students learning about memory management and variable scope in programming. This discussion is particularly beneficial for those looking to deepen their understanding of dynamic memory allocation and its pitfalls.

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   Reactions: 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   Reactions: 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   Reactions: 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   Reactions: 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   Reactions: 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   Reactions: 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 ·
Replies
22
Views
4K
  • · Replies 8 ·
Replies
8
Views
2K
  • · Replies 1 ·
Replies
1
Views
1K
Replies
12
Views
3K
  • · Replies 10 ·
Replies
10
Views
3K
  • · Replies 13 ·
Replies
13
Views
3K
Replies
3
Views
1K
  • · Replies 1 ·
Replies
1
Views
2K
  • · Replies 6 ·
Replies
6
Views
12K
  • · Replies 15 ·
Replies
15
Views
4K