I've built a program which creates an array and ultimately changes the amount of elements available before performing some mathematical calculations. According to my knowledge I've created a "Dynamic Array", (Seeing as I've changed its size in the code), and have discovered it as the problem.

The problem: The program works entirely as expected, performing effectively until "closed" at "return 0;". It always crashes at termination unless I change the circumstances surrounding the array.

Steps Taken:
Original Code:

Code:

Code:

#include <iostream>

using namespace std;
int main()
{
const int array_slots = 5;

cout << "This program has created a CONSTANT 'Integer' for an array. This integer contains the value '5'" << endl <<endl;
cout << "This program will now create the array itself, and supply it with 1 element." << endl << endl;
int numberarray[1] = { 0 };
cout << "This program will now use the CONSTANT INTEGER's value to determine a new 'number of elements' for the array it just created, and initialize each one to zero." << endl << endl;
numberarray[array_slots] = { 0 };

cout << "If this program has succeeded, then you will see this message. Below, you should see the number 4, (5 elements, index starting at zero)." << endl << endl;
cout << sizeof(numberarray);

I was attempting to see if I could create, (Declare?), an array before assigning it a quantity of elements. The IDE stated I couldn't create an array with zero elements, ("zero/no index?"), so I chose 1. AKA "int numberarray[0];" didn't work but [1] did.

The program compiled and ran but crashes at termination. I modified the code to create the array with [5] integers without initialization as seen below.

Code:

Code:

#include <iostream>

using namespace std;
int main()
{
const int array_slots = 5;

cout << "This program has created a CONSTANT 'Integer' for an array. This integer contains the value '5'" << endl <<endl;
cout << "This program will now create the array itself, and supply it with 1 element." << endl << endl;
int numberarray[5];
cout << "This program will now use the CONSTANT INTEGER's value to determine a new 'number of elements' for the array it just created, and initialize each one to zero." << endl << endl;
numberarray[array_slots] = { 0 };

cout << "If this program has succeeded, then you will see this message. Below, you should see the number 4, (5 elements, index starting at zero)." << endl << endl;
cout << sizeof(numberarray);

This didn't crash at termination, everything worked fine. I deduced from this observation that for some reason the program understood and changed the array size from [1] to [5] in the original code, but reverted back to the original value of [1], (Or something other than [5]), prior to termination, causing a crash. I know the size change occurred because the math problems were a success, I know the program is having an issue due to the size change because the crash doesn't occur when the size remains the same throughout.

I also identified that the crash doesn't occur if the "declaration"? of the array is made in global and not within local as seen below:

Code:

Code:

#include <iostream>

using namespace std;

int numberarray[1] = { 0 };

int main()
{
const int array_slots = 5;

cout << "This program has created a CONSTANT 'Integer' for an array. This integer contains the value '5'" << endl <<endl;
cout << "This program will now create the array itself, and supply it with 1 element." << endl << endl;
cout << "This program will now use the CONSTANT INTEGER's value to determine a new 'number of elements' for the array it just created, and initialize each one to zero." << endl << endl;
numberarray[array_slots] = { 0 };

cout << "If this program has succeeded, then you will see this message. Below, you should see the number 4, (5 elements, index starting at zero)." << endl << endl;
cout << sizeof(numberarray);

This led me to deduce that the size of the array can change, if the array isn't declared locally, supporting my theory that the data stored locally within the programs code is having difficulty distinguishing between the original value and its changed value, ([1] and [5]).

My questions:

1. Why does my program run, but crash upon termination in the original code?
2. Why does moving the declaration to global solve the problem?
3. Is the compiler to blame?
4. Is it possible to keep the declaration of the array and the size change of the array local, while also solving the crash problem.

If you could help me solve this I would be most grateful. My understanding of the situation is preventing me from fully grasping how C++ works.

November 10th, 2013, 04:00 AM

D_Drmmr

Re: Crash on termination

Quote:

Originally Posted by JourneyJay

I've built a program which creates an array and ultimately changes the amount of elements available before performing some mathematical calculations. According to my knowledge I've created a "Dynamic Array", (Seeing as I've changed its size in the code), and have discovered it as the problem.

You didn't change the size; you cannot change the size of a static array. What you observed is undefined behavior.

You create an array of size 1. That means the only valid entry is at index 0. You then access the array out of bounds (at index 5). That leads to undefined behavior.
If you want to use a dynamic array, use std::vector.

November 10th, 2013, 04:26 AM

JourneyJay

Re: Crash on termination

Quote:

Originally Posted by D_Drmmr

You didn't change the size; you cannot change the size of a static array. What you observed is undefined behavior.

You create an array of size 1. That means the only valid entry is at index 0. You then access the array out of bounds (at index 5). That leads to undefined behavior.
If you want to use a dynamic array, use std::vector.

If this is the case, then why did the array "Supposedly" hold 5 elements. User input places 5 elements at Index 0-4, reports those numbers, and proceeds to modify them with mathematical calculations. If I was out of bounds, wouldn't the program crash sooner before termination? Everything was effectively stored in memory until return 0 where the crash occurs.

What you said makes perfect sense to me, but it doesn't explain this circumstance.

Also, it doesn't explain the workaround in global. The array is set to 1 in global and changed to 5 later locally, and the crash doesn't occur. Are you absolutely sure I haven't changed the size of the array?

November 10th, 2013, 04:48 AM

Arjay

Re: Crash on termination

Quote:

Originally Posted by JourneyJay

If this is the case, then why did the array "Supposedly" hold 5 elements. User input places 5 elements at Index 0-4, reports those numbers, and proceeds to modify them with mathematical calculations. If I was out of bounds, wouldn't the program crash sooner before termination? Everything was effectively stored in memory until return 0 where the crash occurs.

What you said makes perfect sense to me, but it doesn't explain this circumstance.

Also, it doesn't explain the workaround in global. The array is set to 1 in global and changed to 5 later locally, and the crash doesn't occur. Are you absolutely sure I haven't changed the size of the array?

As was mentioned before, you are experiencing undefined behavior. On a different computer, it might behave differently. Same for different behavior when compiled under a different compiler. As far as explaining what is going on, you can't (because it's undefined behavior).

November 10th, 2013, 06:50 AM

2kaud

Re: Crash on termination

Quote:

If this is the case, then why did the array "Supposedly" hold 5 elements.

The array was holding the 5 elements. c++ doesn't do run-time bounds checking on array access. As the array was only sized for one element, the other 4 elements overwrote what ever happened to be in memory following this one element array. This is called buffer overflow. The results are unpredicatable. Moving the array definiton to different parts of the program just means that a different part of memory is overwritten, possibly with different unpredictable results!

If you know the size of the array at compile time, you can do this

Code:

const int array_slots = 5;
int numberarray[array_slots] = { 0 };

If you don't know the size of the array at compile time, you either have to use dynamically allocated arrays at runtime (using new/delete) or preferably vectors.

November 10th, 2013, 07:16 AM

JourneyJay

Re: Crash on termination

Quote:

Originally Posted by 2kaud

The array was holding the 5 elements. c++ doesn't do run-time bounds checking on array access. As the array was only sized for one element, the other 4 elements overwrote what ever happened to be in memory following this one element array. This is called buffer overflow. The results are unpredicatable. Moving the array definiton to different parts of the program just means that a different part of memory is overwritten, possibly with different unpredictable results!

If you know the size of the array at compile time, you can do this

Code:

const int array_slots = 5;
int numberarray[array_slots] = { 0 };

If you don't know the size of the array at compile time, you either have to use dynamically allocated arrays at runtime (using new/delete) or preferably vectors.

Thanks for the response, it's exactly what I was looking for. I am aware of how to do it correctly, I was testing my knowledge to better understand why it must be done a certain way and why it fails in others. I was attempting to assign it one static value, then change that static value. This would vary from Dynamic arrays as they grow to fit the space needed, where as in this situation I knew I needed 5 "eventually", but I only needed 1 at first. I know it seems like a waste but it has helped gather a much needed portion of knowledge pertaining to the way C++ works. I guess in theory, what I'm suggesting would be similar to a "dynamic array" which is one of only two values, and can't be any other value. Depending on the situation, you need it to be the second value, but it's initially set to the first to save memory...because in most cases you won't need it to be the length of the second value. Both values are static and known.

Thank you for explaining buffer overflow, you've essentially shown my theory that the data was still being held was correct. In a way, it was acting as a dynamic array, growing to accept the new data. I'm assuming that even though that data can be recalled and used, the program still believes there to be only one element, leaving "extra data" that's not supposed to be there by the time the section of code is ready to "return 0", causing a panic and thus, the crash???

November 10th, 2013, 08:19 AM

2kaud

Re: Crash on termination

Quote:

I'm assuming that even though that data can be recalled and used, the program still believes there to be only one element, leaving "extra data" that's not supposed to be there by the time the section of code is ready to "return 0", causing a panic and thus, the crash???

The data could only be recalled and used in this program because it didn't overun other used data storage. If several variables are used in a program, buffer overflow could be likely to overwrite the contents of these variables and change their values. Once your program has been compiled, the program doesn't know anything about the size of arrays. The compiled program only knows the memory address of the start of the variables - be they int, chars or arrays. There is no run-time checking of array bounds as there is in some program languages. The program crashes on the return probably because the buffer overflow has overwritten part of the program so when the program tries to do a return the stack has been corrupted with an incorrect return address. Changing program code like this via buffer overflow is one very widely known 'hacking' technique which is why care needs to be taken during program design/code to eliminate any possible buffer overflow issues.

November 10th, 2013, 04:59 PM

JourneyJay

Re: Crash on termination

Quote:

Originally Posted by 2kaud

The data could only be recalled and used in this program because it didn't overun other used data storage. If several variables are used in a program, buffer overflow could be likely to overwrite the contents of these variables and change their values. Once your program has been compiled, the program doesn't know anything about the size of arrays. The compiled program only knows the memory address of the start of the variables - be they int, chars or arrays. There is no run-time checking of array bounds as there is in some program languages. The program crashes on the return probably because the buffer overflow has overwritten part of the program so when the program tries to do a return the stack has been corrupted with an incorrect return address. Changing program code like this via buffer overflow is one very widely known 'hacking' technique which is why care needs to be taken during program design/code to eliminate any possible buffer overflow issues.