When a pointer is created in scope, what happens to the pointed to variable when the pointer goes out of scope?

10,065

Solution 1

The arrays of characters will hang around for the entire execution of your program because they have static storage duration. This doesn't mean you need to delete them - they're supposed to stay around for the entire duration of your program. In fact, calling delete on it will give you undefined behaviour. You can only delete something that was allocated with new.

The pointers themselves have automatic storage duration and are destroyed when they go out of scope. It's worth noting that the pointer has to be a const char* because the string literal gives you an array of const char. Consider:

void func()
{
  const char* str = "Hello";
}

The array of characters containing Hello\0 exists for the duration of your program. The pointer str only exists for the duration of that function. Nothing needs to be deleted here.

This makes a lot of sense if you think about it. All of these strings you write in your source code have to exist in your executable somewhere. The compiler usually writes these strings of characters into the data segment of your executable. When you run your program, the executable gets loaded into memory along with the data segment containing your strings.

If you have two string literals in your program that have the same or overlapping text, there's no reason the compiler can't optimize it into storing only one of them. Consider:

void func()
{
  const char* str1 = "Hello";
  const char* str2 = "Hello";
  const char* str3 = "lo";
}

The compiler only needs to write the characters Hello\0 into the executable once here. The first two pointers will just point to the H and the third will point to the second l. Your compiler can make optimizations like this. Of course, with this example, the compiler can make an even further optimization by just getting rid of the strings all together - they're not used in any way that contributes to the observable behaviour of the program.

So yes, if you have a million distinct string literals that in some way contribute to the observable behaviour of the program, of course they have to exist as part of your executable.

Solution 2

Your example is, unfortunately, insufficient to address the full picture.

First of all, some simple adhoc vocabulary and explanations: a memory cell is a (typed in C++) zone of memory with a given size, it contains a value. Several memory cells may contain identical values, it does not matter.

There are 3 types of memory cells that you should be considering:

  • "Hello, World!": this memory cell has static storage duration, it exists throughout the duration of the program
  • void foo(int a); and void foo() { int a = 5; }: the memory cell a, in both cases, has automatic storage duration, it will disappear automatically once the function foo returns
  • void foo() { int* a = new 5; }: an anonymous memory cell is created "somewhere" to store the value 5, and a memory cell a with automatic storage duration is created to store the address of the anonymous one

So, what happens when a pointer goes out of scope (disappear) ?

Well, just that. The pointer disappear. Most specifically, nothing special happens to the memory cell it was pointing to.

void foo(int a) {
    int* pointer = &a;
} // pointer disappears, `a` still exists briefly

void foo() {
    int* pointer = 0;
    {
        int a;
        pointer = &a;
    } // a disappears, pointer's value does not change...
} // pointer disappears

Indeed, in C and C++:

  • you can retain the addresses of objects that no longer exists => dangling reference
  • you can lose all addresses to an existing object => memory leak

So what happens when text in char const* text = "Hello, world"; goes out of scope ?

Nothing.

Solution 3

I'd say "nothing" (to answer the title), if it were enough for SO to consider it an answer.

As for your million pointers to characters, whereas the pointers will get popped (though you gotta have quite a stack to hold million pointers) the data they point to will haunt your memories.

Solution 4

The pointer itself occupies space on the "automatic storage" (which is usually the stack). It gets removed once the function returns [or the scope is finished, but technically, nearly all compilers will "wait" until the function returns before the space is freed].

If you call the same function in a loop 1 million times, there will only be ONE pointer at any given time. If you have 1 million functions [and a lot of memory], there will be one pointer for each function that is currently called. E.g.

char *foo()
{
    char *text1 = "Hello";
    return text1;
}

void bar()
{
    char *text2 = "World!";
    printf("%s %s!\n", foo(), text2);
}


void baz()
{
    char *text3 = "Meh";
    bar();
}

int main()
{
    char *text4 = "Main";

    baz();
}

When we enter main, text4 is created on the stack - it is initialized to the string "Main" which is held in some other bit of memory. When we then call baz(), text3 gets created and initialized to "Meh", which calls bar() that creates text2 and points to the text "World", and calls foo which creates text1 and initalizes to Hello. As foo returns, the address inside text1 is given as the return value, and the pointer itself goes away. When printf() is finished, bar returns, and the pointer goes away.

The strings "Main", "Meh", "Hello" and "World" are still staying in place for as long as the program is running.

Share:
10,065
xcdemon05
Author by

xcdemon05

Updated on June 19, 2022

Comments

  • xcdemon05
    xcdemon05 about 2 years

    The title says it all.

    I found an old question that is essentially the same, but I needed a tiny bit further clarification.

    In this question the accepted answer says:

    char* text = "Hello, world"; 
    

    Here an automatic variable (a pointer) is created on the stack and set to point to a value in constant memory, which means:

    • the string literal in "" exists through the whole program execution.
    • you are not responsible for "allocating" or "freeing" it
    • you may not change it. If you want to change it, then you have to allocate some "non-constant memory" and copy it there.

    Is this saying that the pointer gets deleted, but not the data the pointer is pointing to? If I were to create 1,000,000 pointers to characters in a function, when they go out of scope would all of my memory be released? Or just the memory required to make the pointers, leaving the actual characters themselves behind to hog up all my memory?

    • Pete Becker
      Pete Becker over 11 years
      The pointer does not get deleted. It gets destroyed, which in the case of a pointer, does nothing.
  • xcdemon05
    xcdemon05 over 11 years
    Gotcha, so deleting them is a must.
  • djechlin
    djechlin over 11 years
    @xcdemon05 no no no, I think by "haunt your memories" Michael meant "will only exist in your memories."
  • djechlin
    djechlin over 11 years
    @xcdemon05 whether you delete them or not depends. See my answer which I hope explains this.
  • xcdemon05
    xcdemon05 over 11 years
    So cutting out the ambiguousness (not a real word) of my question, in one of my classes i have a function that creates a pointer unsigned char* imageData;, which subsequently gets thrown into another function, and returns engorged with data. After I complete all operations necessary with imageData, if I do not explicitly delete it, the pointer will go out of scope and be freed, but all of the data it was pointing to will remain?
  • Joseph Mansfield
    Joseph Mansfield over 11 years
    It depends on how the memory was allocated. String literals have static storage duration. You cannot delete them. That doesn't mean the string literal is destroyed automatically when the pointer goes out of scope - it just doesn't get destroyed! However, if you allocate the array that imageData points at by doing something like new unsigned char[100] then this array has dynamic storage duration and must be delete[]d, otherwise you'll have a memory leak. The golden rule: Only ever delete/delete[] what you new/new[]!
  • xcdemon05
    xcdemon05 over 11 years
    Okay that makes sense. Thanks!! :)
  • Michael Krelin - hacker
    Michael Krelin - hacker over 11 years
    What I meant depends on how it was allocated. Actually, I did mean "will occupy memory", though I assumed that the data being pointed to was previously allocated. Strictly speaking, this is correct whatever it points to, unless it was deleted elsewhere. It's just that if it wasn't allocated it's okay to occupy memory ;-)