1

Suppose I have a for loop and a local variable inside it:

for(int i=0;i<10;i++){ // Outer loop

    int p[10]; // Local variable

    for(int j=1;j<10;j++){ // Inner loop
    
        p[j] = p[j-1]+1;
    }
}

When all the compiler optimisations are off, it is clear that for the first iteration of the outer loop, the an array p will be allocated in the main memory.

But, is the memory allocated for p freed in the main memory at the end of the first iteration of the Outer loop and allocated again after the start of the subsequent iterations of the Outer loop?

In my opinion, the scope of loops and the scope of methods differ. When function has been completely executed, the local variables are deallocated and the memory is returned back to the OS.

But for loop, when though the scope ends at the end of each iteration, the local variables are not deallocated as they are used in the near future (subsequent iterations). It is only after the loop ends it's execution, the local variables should be deallocated from the main memory.

Kindly correct me if wrong.

Deepak Tatyaji Ahire
  • 4,883
  • 2
  • 13
  • 35
  • "in the main memory" is a meaningless description. In the code you have shown, the array `p` is created with automatic storage duration, uninitialised, at the start of every loop iteration, and then destroyed at the end of the same loop iteration. However, it is up to the implementation (aka compiler) how it achieves that net effect (e.g, it could create the array once, and you couldn't detect the difference within bounds of standard C++). `p` is uninitialised, so the statement `p[j] = p[j-1]+1` in the inner loop accesses uninitialised elements of `p` - and has undefined behaviour. – Peter Apr 02 '21 at 13:24

2 Answers2

0

The behavior of C++ is defined in terms of an abstract machine. In this machine, the memory for an object with automatic storage duration is guaranteed to exist from the start of each entry into the block (execution of code in the block starts) until that execution of the block ends. The block associated with the int p[10] is the one created by the { immediately after the for(int I=0;i<10;i++). Execution of this block starts and ends in each iteration of the for loop.

Although a compiler is likely to implement this loop by allocating stack space once (possibly when the function it is in starts, not just when the for loop is reached), and so the memory that is used to implement int p[10] remains allocated for the entire loop, not just each iteration, the behavior of the program is defined in terms of the abstract machine.

This means that although the stack space remains reserved, optimization by the compiler is not required to behave that way. Optimization may result in code that “forgets” the values in the elements of p from iteration to iteration.

For example, if we execute this code using Apple Clang 11.0 on macOS 10.14.6 with -O3 -std=c++17:

    int p[10];
    for (int i = 0; i < 10; i++)
    {
        if (i == 0)
            p[0] = 0;
        else
            p[0] = p[0]+1;
        for (int j = 1; j < 10; j++)
        {
            p[j] = p[j-1] + 1;
        }
        if (i == 9)
            std::cout << p[0] << '\n';
    }

then the output is “9”, because p[0] was set to 0 in the first iteration and incremented in each later iteration. However, we move the int p[10]; inside the loop, the output is “0”, because compiler optimization did not preserve the value of p[0] between iterations.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
-1

p's scope is the outer loop, so it's destroyed and recreated on the stack on every iteration. The only variable which isn't destroyed is i, but until the outer loop is done. int p[10]; when i=0 is different than int p[10]; when i=1, etc, so when i=1, previous p is already gone. Any other optimization (or assumption) relies on the compiler, architecture, etc.

To clarify, p is living on the stack, its scope will determine when the memory is released (unlike variables on the heap).

Maybe a bit nit-picking, but use modern C++ containers such as std::array or std::vector rather than raw plain C arrays.

To improve resource management, have a look at RAII.

Jose
  • 3,306
  • 1
  • 17
  • 22