steady_progress
steady_progress

Reputation: 3731

dynamic memory allocation in C++ without pointers - what's the point of pointers?

Consider the following C++ program:

#include <iostream>
using namespace std;

void printArray(int p_values[], int size, int elements_set);

int main() 
{
    int next_element = 0;
    int size = 3;
    int p_values[size]; 
    int val;
    cout << "Please enter a number: ";
    cin >> val;

    while (val > 0)
    {
    if (size == next_element+1)
    {
        size *=2;
        int p_values[size];
    }
    p_values[next_element] = val;
    next_element++;
    cout << "Current array values are: " << endl;
    printArray(p_values, size, next_element);
    cout << "Please enter a number (or 0 to exit): ";
    cin >> val;
    }   

}


void printArray(int p_values[], int size, int elements_set) 
{
cout << "Total size of array: " << size << endl;
cout << "Number of slots set so far: " << elements_set << endl;
cout << "Values in the array: " << endl;
    for (int i = 0; i < elements_set; ++i){
        cout << "p_values[" << i << "] = "
             << p_values[i] << endl;
    }
}

What the code does is simply this: 1. the user is asked for a number 2. the number is saved in an array 3. the current content of the array is printed out

Once the array is full, its size is doubled. Such a dynamic increase of an array during runtime is usually done with a pointer. In fact, I was told that such dynamic increasing of an array size is only possible by using pointers.

However, as you can see in the program above, I did not use any pointers but only a static array. Nevertheless, the program dynamically increases the sizeof the array at runtime.

Therefore, my questions are these: 1. Why was I told at university (and also in several books) that, in a C++ program, increasing memory usage during runtime is only possible by using pointers? 2. What's the point of pointers (apart from making it possible to pass variables by reference when calling a function), given the dynamic memory allocation can be done without them?

After having run the program for a while and having entered 8 numbers, the output of the program looks as follows:

Please enter a number (or 0 to exit): 8
Current array values are: 
Total size of array: 12
Number of slots set so far: 8
Values in the array: 
p_values[0] = 1
p_values[1] = 2
p_values[2] = 3
p_values[3] = 4
p_values[4] = 5
p_values[5] = 6
p_values[6] = 7
p_values[7] = 8
Please enter a number (or 0 to exit): 

Upvotes: 0

Views: 2154

Answers (4)

deft artisan
deft artisan

Reputation: 15

Nested definition of an identically denoted array, not dynamic re-allocation, proving ineffective to the obvious intent and ultimately producing memory corruption due to the deregulated input.

Upvotes: 0

Peter
Peter

Reputation: 36597

As a matter of fact

int size = 3;
int p_values[size]; 

is not valid C++. This feature (variable length arrays) was introduced into C with the 1999 standard, and is not in any C++ standard, or is it proposed to be added. Some C++ compilers (and some C compilers predating the 1999 C standard) support this feature as a non-standard extension.

Even if we assume a compiler that supports C's VLAs, this

int size = 3;
int p_values[size]; 

/* other code */
{
    size *=2;
    int p_values[size];
}

does not resize p_values. It temporarily creates another array, within the nested scope (i.e. in the {}) that no longer exists outside the scope.

Upvotes: 3

James
James

Reputation: 8586

Your code doesn't work. Your 'reallocation' doesn't do anything - you're creating another array which shadows the name. In the mean time, you're overwriting memory that's not yours (e.g. p_values[9] is where the size variable is stored). Keep going, and it becomes more clear:

Please enter a number: 1
Current array values are:
Total size of array: 3
Number of slots set so far: 1
Values in the array:
p_values[0] = 1
Please enter a number (or 0 to exit): 2
Current array values are:
Total size of array: 3
Number of slots set so far: 2
Values in the array:
p_values[0] = 1
p_values[1] = 2
Please enter a number (or 0 to exit): 3
Current array values are:
Total size of array: 6
Number of slots set so far: 3
Values in the array:
p_values[0] = 1
p_values[1] = 2
p_values[2] = 3
Please enter a number (or 0 to exit): 4
Current array values are:
Total size of array: 6
Number of slots set so far: 4
Values in the array:
p_values[0] = 1
p_values[1] = 2
p_values[2] = 3
p_values[3] = 4
Please enter a number (or 0 to exit): 5
Current array values are:
Total size of array: 6
Number of slots set so far: 5
Values in the array:
p_values[0] = 1
p_values[1] = 2
p_values[2] = 3
p_values[3] = 4
p_values[4] = 5
Please enter a number (or 0 to exit): 6
Current array values are:
Total size of array: 12
Number of slots set so far: 6
Values in the array:
p_values[0] = 1
p_values[1] = 2
p_values[2] = 3
p_values[3] = 4
p_values[4] = 5
p_values[5] = 6
Please enter a number (or 0 to exit): 7
Current array values are:
Total size of array: 12
Number of slots set so far: 7
Values in the array:
p_values[0] = 1
p_values[1] = 2
p_values[2] = 3
p_values[3] = 4
p_values[4] = 5
p_values[5] = 6
p_values[6] = 7
Please enter a number (or 0 to exit): 8
Current array values are:
Total size of array: 12
Number of slots set so far: 8
Values in the array:
p_values[0] = 1
p_values[1] = 2
p_values[2] = 3
p_values[3] = 4
p_values[4] = 5
p_values[5] = 6
p_values[6] = 7
p_values[7] = 8
Please enter a number (or 0 to exit): 9
Current array values are:
Total size of array: 12
Number of slots set so far: 10
Values in the array:
p_values[0] = 1
p_values[1] = 2
p_values[2] = 3
p_values[3] = 4
p_values[4] = 5
p_values[5] = 6
p_values[6] = 7
p_values[7] = 9
p_values[8] = 10
p_values[9] = 12
Please enter a number (or 0 to exit): 11
Current array values are:
Total size of array: 12
Number of slots set so far: 11
Values in the array:
p_values[0] = 1
p_values[1] = 2
p_values[2] = 3
p_values[3] = 4
p_values[4] = 5
p_values[5] = 6
p_values[6] = 7
p_values[7] = 11
p_values[8] = 11
p_values[9] = 12
p_values[10] = 11
Please enter a number (or 0 to exit): 12
Current array values are:
Total size of array: 24
Number of slots set so far: 12
Values in the array:
p_values[0] = 1
p_values[1] = 2
p_values[2] = 3
p_values[3] = 4
p_values[4] = 5
p_values[5] = 6
p_values[6] = 7
p_values[7] = 12
p_values[8] = 12
p_values[9] = 24
p_values[10] = 11
p_values[11] = 12
Please enter a number (or 0 to exit): 13
Current array values are:
Total size of array: 24
Number of slots set so far: 13
Values in the array:
Segmentation fault (core dumped)

Upvotes: 2

Sam Varshavchik
Sam Varshavchik

Reputation: 118300

    size *=2;
    int p_values[size];
}

Nope. This does not increase the size of the existing p_values array, declared at the beginning of the function. This declares a different array named p_values, in the inner scope...

...and since the inner scope immediately ends here, this has no effect whatsoever. The loop the continues and runs off the end of the original p_values array, resulting in undefined behavior and memory corruption.

Nevertheless, the program dynamically increases the sizeof the array at runtime.

No, it didn't. The size of the existing array was not dynamically increased. A different, larger variable-length array was declared in inner scope, and immediately destroyed. The original array remained at its original size, and undefined behavior resulted.

Just keep inputting more values into the array, and at some point you'll end up smashing the return address on the stack, resulting in a segfault when main() returns (assuming your compiler implements variable-length arrays dynamically by adjusting the size of the current function's stack frame).

Upvotes: 8

Related Questions