-1

I'm fairly new to C++ so please forgive me for my ignorance. I'm under the impression that anything between { and } is called a scope, and that you can create a separate scope inside a function, or anything else, just by adding more brackets. For example:

int foo(){
    std::cout << "I'm inside the scope of foo" << std::endl;
    {
        std::cout << "I'm inside a scope that's inside the scope of foo" << std::endl;
    }
}

I was learning about this in relation to pointers and memory leaks. My understanding is when you leave a scope all variables should be freed from memory unless the memory was manually allocated with new or malloc. In my testing, however, this does not seem to be the case. I've written the following script to test this:

#include <iostream>

void test(){

    {
        int regdata = 240;
        int* pointerInt = new int(1);
        *pointerInt = 15;
        std::cout << "RegData Addr: " << &regdata << std::endl;
        std::cout << "Value:        " << regdata << std::endl;
        std::cout << "Pointer Addr: " << &pointerInt << std::endl;
        std::cout << "Pointer:      " << pointerInt << std::endl;
        std::cout << "Value:        " << *pointerInt << std::endl;
        std::cout << std::endl;
        std::cout << "Press any key then enter to leave the scope.";
        char temp;
        std::cin >> temp;
        //delete pointerInt;
    }

    std::cout << "The scope has been left." << std::endl;
    std::cout << "Press any key then enter to leave the function.";
    char temp;
    std::cin >> temp;
}

int main(){
    test();
    std::cout << "The function has been left." << std::endl;
    std::cout << "Press any key then enter to leave the program.";
    char temp;
    std::cin >> temp;
}

I start this program on my Windows 10 computer and have been monitoring the memory usage using the program Cheat Engine. Now, depending on whether or not I have delete commented out it will delete the bytes that hold 15 and replace them with random bytes when I leave the scope as it should. However, the memory holding the 240 is not freed until after I leave the scope of test (at which point the 240 is replaced with 1). And regardless of if the delete is commented out, the actual pointer itself is never deleted out of memory.

Is my compiler or my machine not compiling/running my code correctly? Or am I misunderstanding memory management between scopes? If it's the latter, please correct me so I can properly understand what is supposed to happen. Also let me know if something doesn't make sense!

tayler6000
  • 103
  • 1
  • 8
  • 1
    Anything you allocated with `new`, you need to deallocate with `delete` or else there will be a memory leak. Stack-variables (like `regdata` and `pointerInt`) are automatically freed when leaving a scope, but heap allocations they might point to (like the integer you allocated with `new int(1)`) are not. – Jeremy Friesner Jun 27 '22 at 04:04
  • 4
    The problem here is that there's no real way to detect that memory has been freed. It's no longer safe to use that memory, but it will continue to contain the same value until something else uses that memory and overwrites its contents Which might take an arbitrary length of time. – Jerry Coffin Jun 27 '22 at 04:05
  • Releasing freed memory in C++ heap back to the *kernel* is not so easy to do. The memory must be contiguous and can only be freed in *full pages*. – Jason Jun 27 '22 at 04:05
  • 3
    The tools you're using the monitor memory usage are operating at a somewhat different level than the programming language standard you're asking about. When C++ releases memory, that really represents a negotiation between your process and the underlying OS, meaning that you won't necessarily see freed memory reflected in Cheat Engine. – Nathan Pierson Jun 27 '22 at 04:05
  • 1
    "My understanding is when you leave a scope all variables should be freed from memory": your understanding is incorrect. Generally speaking, compilers allocate all local variable space required by a method on entry to the method, via a stack frame, rather than scope by scope, and release the stack frame on exit from that method. What *is* guaranteed is that all *objects* declared with automatic storage within a scope are *destroyed* by calling their destructors on exit from that scope. That can release memory to the heap, but C++ isn't guaranteed to ever release heap memory back to the OS. – user207421 Jun 27 '22 at 04:09
  • 2
    use destructors to detect when your object has freed. – Mehran Jun 27 '22 at 04:13
  • @JerryCoffin Well the thing is, in running this program for variable lengths of time, `regdata` is ALWAYS set to `1` when I leave the scope of `test` which makes me think it's the program doing it and that it's not truly free, though I suppose there isn't a way to truly know for sure. – tayler6000 Jun 27 '22 at 04:16
  • @tayler - It is free when you leave the scope, and *can* then be reused. But there is no rule that it *has to* be reused immediately (or at all). – BoP Jun 27 '22 at 04:37
  • @user207421 we aren't answering his question. we are just confusing him. the website fully covers this topic. – Mehran Jun 27 '22 at 05:00
  • @Mehran The only thing you should be citing here is the applicable section(s) of the C++ Language Standard. Third-party sites have no more status than SO itself. I was unable to find any mention of storage deallocation with scope on a quick look. – user207421 Jun 27 '22 at 05:01
  • @user207421 the website teaches all things step-by-step and also covers semantics of stack and heap so well. – Mehran Jun 27 '22 at 05:09
  • @user207421 https://www.learncpp.com/cpp-tutorial/dynamic-memory-allocation-with-new-and-delete/ and https://www.learncpp.com/cpp-tutorial/the-stack-and-the-heap/ but reading all pages in the default order is better. trust the author, i haven't seen any deprecated topic. – Mehran Jun 27 '22 at 05:25
  • Does this answer your question? https://stackoverflow.com/questions/6493299/will-visual-c-runtime-malloc-free-return-memory-to-os – n. m. could be an AI Jun 27 '22 at 05:27
  • @user207421 can I recite other websites in the answers is it legal? it's better than writing something not accurate. – Mehran Jun 27 '22 at 05:37
  • 2
    @Mehran Generally speaking, it is better to write your own answer to a question - possibly with a link to supporting info (e.g. people often write an answer and either quote [with attribution] or link to a page on cppreference.com for further details for reference). Simply reciting from another site is discouraged, both because of potential breach of copyright, and it often does not really address the question at hand. Link-only answers don't help much for the same reason. In any event learncpp.com is patchy (e.g. often inaccurate or outdated) so copying/linking its content is often down-voted – Peter Jun 27 '22 at 07:53
  • @Peter i'm against your opinion about learncpp.com, that's new as the tutorial is under construction yet. have you found a outdated thing in it? – Mehran Jun 27 '22 at 08:50
  • 1
    @Mehran - Let me put it this way. That tutorial you linked to about heap and stack gives the impression that memory in C++ is managed in those terms. In fact, no C++ (or C) standard mentions anything about heap and stack as memory areas. (The C++ standard library has a `stack` which is a container adapter i.e. different). The terms heap and stack memory originated in a particular hardware architecture over two decades ago - and the description in parts of that tutorial are specific to compilers that targeted some such platforms, whereas the C++ standard (by design) is hardware neutral. – Peter Jun 27 '22 at 09:22
  • @Peter Yes, this semantics are relatively close to hardware, and sometimes providing some details about implementations may improve understanding. i personally hadn't learned this fully until i learned some ARM assembly . it's true that implementations maybe different, but, he just tries to give some example. however i haven't seen any better free and online tutorial for C++. – Mehran Jun 27 '22 at 11:58

2 Answers2

2

Memory is not "freed" when you leave a scope. The lifetime of all variables with automatic storage duration that were declared within that scope end. What happens when the lifetime of a variable ends? For simple values like an int or a pointer: likely absolutely nothing. The lifetime of the variable has ended, so attempting to use it results in undefined behavior, but usually nothing will immediately happen to the value. The compiler knows that the storage in which the variable resided is now available to be re-used, but until it actually re-uses it the old value will likely continue to exist. A compiler could immediately zero out the memory of variables whose lifetime has ended, and for a debug build maybe it will, but doing so would take time so most compilers won't bother.

Miles Budnek
  • 28,216
  • 2
  • 35
  • 52
1

regdata is stored on the stack so the memory it uses will never normally be "freed" until the end of the thread that the code is running in.

What does happen is that the stack memory is now available again to be used for something else. Your calls to std::cout and std::cin will both need to use a certain amount of stack memory, if they use enough memory then they'll overwrite all of the values in your inner scope (depending on the implementation of your compiler, there's no guarantee that it'll reuse the inner scopes stack memory later in the function, it might decide it's faster to use more stack memory instead).

This is why regdata is always being overwritten with 1, it's a coincidence of later stack usage rather than a deliberate action by the compiler. Some compilers might deliberately overwrite stack memory after its released to help with debugging but in a normal release build that would be an unnecessary waste of time.

Alan Birtles
  • 32,622
  • 4
  • 31
  • 60