CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 8 of 8
  1. #1
    Join Date
    Nov 2013
    Posts
    5

    Crash on termination

    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);
    
    	cout << "Please enter a new value for integer/index 0, (Element ONE), in the array: ";
    	cin >> numberarray[0]; cout << endl << endl;
    	cout << "Now, enter a value for the remaining 4 elements. Remember, as these are integers they must be numbers." << endl << endl
    	<< "Press enter after you have entered each element." << endl << endl;
    
    	cout << "Element 2: "; cin >> numberarray[1];
    	cout << "Element 3: "; cin >> numberarray[2];
    	cout << "Element 4: "; cin >> numberarray[3];
    	cout << "Element 5: "; cin >> numberarray[4];
    	cout << endl << endl;
    
    	cout << "You should now see the values of multiple problems performed using the elements provided." << endl << endl;
    	cout << "Index 0 multiplied by Index 3: ";
    	         int comboA;
    			 comboA = numberarray[0] * numberarray[3];
    			 cout << comboA << endl << endl;
    	cout << "The combination of the above value, minus element 5: "
    		     << comboA - numberarray[4] << endl << endl;
    	cout << "Element 3 PLUS index 0: " << numberarray[2] + numberarray[0] << endl << endl;
    	cout << " The combination of Element 1 multiplied by Element 4, (Seen above ^^^), multiplied by index 4: "
    		<< comboA * numberarray[4] << endl << endl;
    	cout << "If this program has reached this line, chances are it has been successful in its attempt to run correctly." << endl << endl;
    	cout << "Enter any integer value to exit: ";
    
    	int programhold = 0;
    	cin >> programhold;
    	return 0;
    }
    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);
    
    	cout << "Please enter a new value for integer/index 0, (Element ONE), in the array: ";
    	cin >> numberarray[0]; cout << endl << endl;
    	cout << "Now, enter a value for the remaining 4 elements. Remember, as these are integers they must be numbers." << endl << endl
    	<< "Press enter after you have entered each element." << endl << endl;
    
    	cout << "Element 2: "; cin >> numberarray[1];
    	cout << "Element 3: "; cin >> numberarray[2];
    	cout << "Element 4: "; cin >> numberarray[3];
    	cout << "Element 5: "; cin >> numberarray[4];
    	cout << endl << endl;
    
    	cout << "You should now see the values of multiple problems performed using the elements provided." << endl << endl;
    	cout << "Index 0 multiplied by Index 3: ";
    	         int comboA;
    			 comboA = numberarray[0] * numberarray[3];
    			 cout << comboA << endl << endl;
    	cout << "The combination of the above value, minus element 5: "
    		     << comboA - numberarray[4] << endl << endl;
    	cout << "Element 3 PLUS index 0: " << numberarray[2] + numberarray[0] << endl << endl;
    	cout << " The combination of Element 1 multiplied by Element 4, (Seen above ^^^), multiplied by index 4: "
    		<< comboA * numberarray[4] << endl << endl;
    	cout << "If this program has reached this line, chances are it has been successful in its attempt to run correctly." << endl << endl;
    	cout << "Enter any integer value to exit: ";
    
    	int programhold = 0;
    	cin >> programhold;
    	return 0;
    }
    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);
    
    	cout << "Please enter a new value for integer/index 0, (Element ONE), in the array: ";
    	cin >> numberarray[0]; cout << endl << endl;
    	cout << "Now, enter a value for the remaining 4 elements. Remember, as these are integers they must be numbers." << endl << endl
    	<< "Press enter after you have entered each element." << endl << endl;
    
    	cout << "Element 2: "; cin >> numberarray[1];
    	cout << "Element 3: "; cin >> numberarray[2];
    	cout << "Element 4: "; cin >> numberarray[3];
    	cout << "Element 5: "; cin >> numberarray[4];
    	cout << endl << endl;
    
    	cout << "You should now see the values of multiple problems performed using the elements provided." << endl << endl;
    	cout << "Index 0 multiplied by Index 3: ";
    	         int comboA;
    			 comboA = numberarray[0] * numberarray[3];
    			 cout << comboA << endl << endl;
    	cout << "The combination of the above value, minus element 5: "
    		     << comboA - numberarray[4] << endl << endl;
    	cout << "Element 3 PLUS index 0: " << numberarray[2] + numberarray[0] << endl << endl;
    	cout << " The combination of Element 1 multiplied by Element 4, (Seen above ^^^), multiplied by index 4: "
    		<< comboA * numberarray[4] << endl << endl;
    	cout << "If this program has reached this line, chances are it has been successful in its attempt to run correctly." << endl << endl;
    	cout << "Enter any integer value to exit: ";
    
    	int programhold = 0;
    	cin >> programhold;
    	return 0;
    }
    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.

  2. #2
    Join Date
    Jul 2005
    Location
    Netherlands
    Posts
    2,042

    Re: Crash on termination

    Quote Originally Posted by JourneyJay View Post
    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.
    Code:
    	const int array_slots = 5;
    	int numberarray[1] = { 0 };
    	numberarray[array_slots] = { 0 };
    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.
    Cheers, D Drmmr

    Please put [code][/code] tags around your code to preserve indentation and make it more readable.

    As long as man ascribes to himself what is merely a posibility, he will not work for the attainment of it. - P. D. Ouspensky

  3. #3
    Join Date
    Nov 2013
    Posts
    5

    Re: Crash on termination

    Quote Originally Posted by D_Drmmr View Post
    You didn't change the size; you cannot change the size of a static array. What you observed is undefined behavior.
    Code:
    	const int array_slots = 5;
    	int numberarray[1] = { 0 };
    	numberarray[array_slots] = { 0 };
    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?

  4. #4
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: Crash on termination

    Quote Originally Posted by JourneyJay View Post
    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).

  5. #5
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    Re: Crash on termination

    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.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  6. #6
    Join Date
    Nov 2013
    Posts
    5

    Re: Crash on termination

    Quote Originally Posted by 2kaud View Post
    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???

  7. #7
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    Re: Crash on termination

    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.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  8. #8
    Join Date
    Nov 2013
    Posts
    5

    Re: Crash on termination

    Quote Originally Posted by 2kaud View Post
    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.
    Thank you. It makes perfect sense.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured