C++ Why make new int is error? - c++

Why my code error ?
int *x ;
x = new int[5];
x[0] = 3;
x[1] = 4;
x[2] = 5;
x[3] = 1;
x[4] = 2;
x[5] = 11;
x[6] = 90;
int *y ;
y = new int[5];
cout << "if no error, then this command should be run" << endl;
but the output is :
Process exited after 0.07883 seconds with return value 3221226356
Press any key to continue . . .

Before writing code, think of the logic for a moment. If you could allocate space for 5 ints and then straightaway carry on storing 10 (or anything beyond 5 elements, for that matter), what's the point of allocating anything, in first place?
What you're seeing here is memory overrun, which invokes undefined behavior. Don't do that.
To elaborate, on 0-based indexing system, the valid index for the above case will be 0 to 4, anything beyond that is going to access out of bound memory, which invokes the UB.

You allocate 5 integers then try to store 7.
Why do you expect that to work?

You can't access the 5 and 6 position of an array of length 5.
You only can access x[0], x[1], x[2],x[3] and x[4] positions.
So if an array is of n positions you can access up to position n-1 because the first position is 0.

Why make new int is error
There is nothing wrong with make new int. The problem is with the size of your array at declaration.
Let's look at your code for a moment:
int *x ;
x = new int[5];
x[0] = 3;
x[1] = 4;
x[2] = 5;
x[3] = 1;
x[4] = 2;
x[5] = 11;
x[6] = 90;
You start by declaring a pointer int variable in the first line.
You then assign exactly 5 consecutive spaces in memory, with x pointing to the first one.
You then assign values to the 5 blocks of memory, starting at 0 and going up to 4, which is valid, as 0-4 is 5 blocks of memory is what the compiler has initialy allocated for you in memory.
Then, you try to store 11 in x[5] and 90 in x[6]. This is where undefined behaviour occurs.
When you try to move outside of the index specified in your array, your program is trying to access memory that it should not, because the compiler has only allotted a fixed number of spaces in memory initially. You do not know what the memory space that comes right after x[4] has stored in it, if anything at all, because the compiler has only allotted you memory for an array of index 0 to 4. x[5] may be empty, in which your program sill continue running, or it may be used in some other process of your machine, and trying to access that is disallowed, which leads to a segmentation fault in your case.
This is why it is called undefined behaviour; when an array index that is outside of the array size declared initially may point to a memory space that is or is not empty. If it is empty, then the program will continue running (this is wrong), but if it is not empty, then your program will terminate due to a runtime error: segmentation fault.
To fix this, change your array size to:
x = new int [7];
So that the compiler will find 7 consecutive spaces of memory instead of 5.

Related

Elements retained even after using delete[]

My code is :
#include <iostream>
using namespace std;
int main() {
// your code goes here
int* a;
a = new int[5];
for(int i = 0; i < 5; i++)
cin>>a[i];
for(int i = 0; i < 5; i++)
cout<<a[i]<<" ";
delete[] a;
cout<<"NEW MEM ";
a = new int[5];
for(int i = 0; i < 5; i++)
cout<<a[i]<<" ";
return 0;
}
INPUT : 1 2 14 4 5 and
OUTPUT : 1 2 14 4 5 NEW MEM 0 0 14 4 5
Please explain why i am not getting OUTPUT : 1 2 14 4 5 NEW MEM 0 0 0 0 0
Perhaps you were expecting that new int[5] would zero-initialise the new block of memory.
Well, it doesn't! And that's pretty much that. C++ doesn't do things you didn't ask for, because if you didn't want them, that's an unnecessary performance hit.
It looks like your new memory block just so happens to be found at the same place as the last one, and now you're [partially] observing the values left behind from the last one. Technically these values are unspecified, and reading them means your program has undefined behaviour. You have to provide your own fresh values for these new array elements before you can use them for anything truly meaningful.
Or perhaps you were expecting the delete[] to zero-initialise the dying block of memory.
That doesn't happen either. There's really no point in zeroing-out objects just as they are about to wither out of existence. Again, C++ won't waste time on things like this.
You can make the zero-initialisation happen with new int[5]() but I don't see a good reason to do so here.
Because with:
a = new int[5];
You are not (default) initializing your array to zeros nor any other value as pointed out in the comments below. You are only allocating space for five ints on the free-store and printing out the values of an uninitialized array which is undefined behavior.
Initialize your array values to 0:
a = new int[5] {0};
or:
a = new int[5] {};
Or provide values for all the elements:
a = new int[5] { 1, 2, 14, 4, 5 };

c++ 2D array allocation

Could someone please explain what each line is really doing here. I know overall it allocates 4 spaces, but I don't understand the details.
int** arrayArray;
arrayArray= new int*[4];
for (int x = 0; x < 4; ++x)
{ arrayArray[x] = new int[4];}
Your array is a 2D array, so it size is in forms of "x by y". The total ints your array contains will be x*y. I will call x as the row number and y as the column number.
It seems like you need a array with total 4 ints, so your row number and column number should have a product of 4, for example 2x2. Keep in mind that the following answer is dealing with a 4x4 array, which has 16 total ints.
Allocation:
int** arrayArray;
This line decelar a variable arrayArray, which is a pointer of ( pointer of int ). Like
(arrayArray) -> * -> int
So arrayArray[0] gives you a pointer of int, and arrayArray[0][0] therefore give you an int (which is in the array).
arrayArray = new int*[4];
This line allocate a space that can contain 4 pointers of int, and set the arrayArray to point to that space (don't forget that arrayArray is a pointer of a pointer of int. ).
Here the 4 means row number.
for (int x = 0; x < 4; ++x)
arrayArray[x] = new int[4];
For every pointer in arrayArray, set it to point to a space for 4 ints.
Here the 4 in new int[4] means column number.
So the structure of this array will be something like
Deallocation (free):
Notice that arrayArray by it self is just a pointer to 4 other pointer. If you want to free the entire array, you don't just free the space for the 4 pointers. You need to free every space these pointer points to, else you will cause memory leak. For example you want to free the entire array, it is just the reverse of allocation, first free all the space arrayArray points to:
for (int x = 0; x < 4; ++x)
delete[] arrayArray[x];
In C++, if you want to delete a space allocated by new something[], you need delete[] instead of delete.
Then free the array itself:
delete[] arrayArray;
int** arrayArray;
arrayArray= new int*[4];
The above code initializes 4 locations that can hold pointers to 4 int*
The next couple of lines allocate 4 int spaces for each int*, so a total of 4*4=16 integer spaces.
for (int x = 0; x < 4; ++x)
{ arrayArray[x] = new int[4];}
Now as per your comment, you want only 4 integer spaces. So that means your 2d array would be 2x2.
So your code should look something like:
int** arrayArray;
arrayArray= new int*[2];
for (int x = 0; x < 2; ++x)
{ arrayArray[x] = new int[2];}
This way you will only allocate 2 int* locations and 2 int spaces that they can point to.

I don't understand how to create and use dynamic arrays in C++

Okay so I have;
int grid_x = 5
int * grid;
grid = new int[grid_x];
*grid = 34;
cout << grid[0];
Should line 3 create an array with 5 elements? Or fill the first element with the number 5?
Line 4 fills the first element, how do I fill the rest?
Without line 4, line 5 reads "-842150451".
I don't understand what is going on, I'm trying to create a 2 dimensional array using x and y values specified by the user, and then fill each element one by one with numeric values also specified by the user. My above code was an attempt to try it out with a 1 dimensional array first.
The default C++ way of creating a dynamic(ally resizable) array of int is:
std::vector<int> grid;
Don't play around with unsafe pointers and manual dynamic allocation when the standard library already encapsulates this for you.
To create a vector of 5 elements, do this:
std::vector<int> grid(5);
You can then access its individual elements using []:
grid[0] = 34;
grid[1] = 42;
You can add new elements to the back:
// grid.size() is 5
grid.push_back(-42);
// grid.size() now returns 6
Consult reference docs to see all operations available on std::vector.
Should line 3 create an array with 5 elements?
Yes. It won't initialise them though, which is why you see a weird value.
Or fill the first element with the number 5?
new int(grid_x), with round brackets, would create a single object, not an array, and specify the initial value.
There's no way to allocate an array with new and initialise them with a (non-zero) value. You'll have to assign the values after allocation.
Line 4 fills the first element, how do I fill the rest?
You can use the subscript operator [] to access elements:
grid[0] = 34; // Equivalent to: *(grid) = 34
grid[1] = 42; // Equivalent to: *(grid+1) = 42
// ...
grid[4] = 77; // That's the last one: 5 elements from 0 to 4.
However, you usually don't want to juggle raw pointers like this; the burden of having to delete[] the array when you've finished with it can be difficult to fulfill. Instead, use the standard library. Here's one way to make a two-dimensional grid:
#include <vector>
std::vector<std::vector<int>> grid(grid_x, std::vector<int>(grid_y));
grid[x][y] = 42; // for any x is between 0 and grid_x-1, y between 0 and grid_y-1
Or might be more efficient to use a single contiguous array; you'll need your own little functions to access that as a two-dimenionsal grid. Something like this might be a good starting point:
template <typename T>
class Grid {
public:
Grid(size_t x, size_t y) : size_x(x), size_y(y), v(x*y) {}
T & operator()(size_t x, size_t y) {return v[y*size_x + x];}
T const & operator()(size_t x, size_t y) const {return v[y*size_x + x];}
private:
size_t size_x, size_y;
std::vector<T> v;
};
Grid grid(grid_x,grid_y);
grid(x,y) = 42;
Should line 3 create an array with 5 elements? Or fill the first element with the number 5?
Create an array with 5 elements.
Line 4 fills the first element, how do I fill the rest?
grid[n] = x;
Where n is the index of the element you want to set and x is the value.
Line 3 allocates memory for 5 integers side by side in memory so that they can be accessed and modified by...
The bracket operator, x[y] is exactly equivalent to *(x+y), so you could change Line 4 to grid[0] = 34; to make it more readable (this is why grid[2] will do the same thing as 2[grid]!)
An array is simply a contiguous block of memory. Therefore it has a starting address.
int * grid;
Is the C representation of the address of an integer, you can read the * as 'pointer'. Since your array is an array of integers, the address of the first element in the array is effectively the same as the address of the array. Hence line 3
grid = new int[grid_x];
allocates enough memory (on the heap) to hold the array and places its address in the grid variable. At this point the content of that memory is whatever it was when the physical silicon was last used. Reading from uninitialised memory will result in unpredictable values, hence your observation that leaving out line 4 results in strange output.
Remember that * pointer? On line four you can read it as 'the content of the pointer' and therefore
*grid = 34;
means set the content of the memory pointed to by grid to the value 34. But line 3 gave grid the address of the first element of the array. So line 4 sets the first element of the array to be 34.
In C, arrays use a zero-based index, which means that the first element of the array is number 0 and the last is number-of-elements-in-the-array - 1. So one way of filling the array is to index each element in turn to set a value to it.
for(int index = 0; index < grid_x; index++)
{
grid[index] = 34;
}
Alternatively, you could continue to use a pointer to do the same job.
for(int* pointerToElement = grid; 0 < grid_x; grid_x-- )
{
// save 34 to the address held by the pointer
/// and post-increment the pointer to the next element.
*pointerToElement++ = 34;
}
Have fun with arrays and pointers, they consistently provide a huge range of opportunities to spend sleepless hours wondering why your code doesn't work, PC reboots, router catches fire, etc, etc.
int grid_x = 5
int * grid;
grid = new int[grid_x];
*grid = 34;
cout << grid[0];
Should line 3 create an array with 5 elements? Or fill the first
element with the number 5?
Definitely the former. With the operator "new" you are allocating memory
Line 4 fills the first element, how do I fill the rest?
Use operator [], e.g.:
for int (i=0; i < grid_x; i++) { //Reset the buffer
grid[i] = 0;
}
Without line 4, line 5 reads "-842150451".
You are just reading uninitialized memory, it could be any value.
I don't understand what is going on, I'm trying to create a 2
dimensional array using x and y values specified by the user, and then
fill each element one by one with numeric values also specified by the
user. My above code was an attempt to try it out with a 1 dimensional
array first.
Other users explained how to use vectors. If you have to set only once the size of your array, I usually prefer boost::scoped_array which takes care of deleting when the variable goes out of scope.
For a two dimensional array of size not known at compile time, you need something a little bit trickier, like a scoped_array of scoped_arrays. Creating it will require necessarily a for loop, though.
using boost::scoped_array;
int grid_x;
int grid_y;
///Reading values from user...
scoped_array<scoped_array<int> > grid(new scoped_array<int> [grid_x]);
for (int i = 0; i < grid_x; i++)
grid[i] = scoped_array<int>(new int[grid_y] );
You will be able then to access your grid elements as
grid[x][y];
Note:
It would work also taking scoped_array out of the game,
typedef int* p_int_t;
p_int_t* grid = new p_int_t [grid_x];
for (int i = 0; i < grid_x; i++)
grid[i] = new int[grid_y];
but then you would have to take care of deletion at the end of the array's life, of ALL sub arrays.

Offset calculation in 3D array

In the following code,
int arr[3][2][2]={1,2,3,4,5,6,7,8,9,10,11,12};
cout<<arr[0][0][5]<<endl;
cout<<arr[1][3][0]<<endl;
I get output as, 6 and 11.
How is it indexing an element out of its range?
eg- here the sizes are, depth= 3 col=2 row=2 , In thet case arr[0][0][5] means 5th row, which doesnt exist! Can anyone throw light on this.
Technically, you are invoking undefined behaviour.*
But, most likely, what's happening is that the compiler is calculating the address to read as:
(int *)arr + x*(2*2) + y*2 + z
because your 3D array is really stored in memory as a contiguous linear array.
So in your [0][0][5] case, it's simply reading the (0*4+0*2+5)=5th element (zero-based) of that linear array, which is 6.
Similarly for [1][3][0], it's reading the (1*4+3*2+0)=10th element, which is 11.
* This was discussed in a question I asked: One-dimensional access to a multidimensional array: well-defined C?.
Remember the last time you had a C-style string that you forgot to terminate?
char str[] = {'a','b','c'};
cout << str;
Remember how you printed "abc" then any random gubbins in memory after it because the program kept reading past the array?
It'll do that; it'll just keep going and pull out whatever happens to be there, even though doing so is undefined. The compiler simply doesn't need to warn you about this; you are supposed to figure it out for yourself.
In your case, the data for the next row probably happens to be in memory at that spot.
It's like that:
int arr[depth][col][row];
int temp = arr[x][y][z];
then temp = arr[x * (col * row) + y * row + z]

Help me understand this Strange C++ code

This was a question in our old C++ exam. This code is driving me crazy, could anyone explain what it does and - especially - why?
int arr[3]={10,20,30};
int *arrp = new int;
(*(arr+1)+=3)+=5;
(arrp=&arr[0])++;
std::cout<<*arrp;
This statement writes to the object *(arr+1) twice without an intervening sequence point so has undefined behavior.
(*(arr+1)+=3)+=5;
This statement writes to the object arrp twice without an intervening sequence point so has undefined behavior.
(arrp=&arr[0])++;
The code could result in anything happening.
Reference: ISO/IEC 14882:2003 5 [expr]/4: "Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression."
(*(arr+1)+=3)+=5;
arr + 1 - element with index 1
*(arr + 1) - value of this element
(arr + 1) += 3 - increase by 3
((arr+1)+=3)+=5 - increase by 5;
so arr[1] == 28
(arrp=&arr[0])++;
arr[0] - value of element 0
&arr[0] - address of element 0
arrp=&arr[0] - setting arrp to point to elem 0
(arrp=&arr[0])++ - set arr to point to elem 1
result: 28
This line:
(*(arr+1)+=3)+=5;
produces the same result as this (see footnote):
arr[1] += 3;
arr[1] += 5;
This line:
(arrp=&arr[0])++;
produces the same result as this (see footnote):
int* arrp = arr+1;
So this line:
std::cout<<*arrp
prints out 28.
But this code leaks memory because int *arrp = new int; allocates a new int on the heap which will be lost on assignment by (arrp=&arr[0])++;
Footnote: Of course I'm assuming an absence of weirdness.
Edit: Apparently some of the lines in fact lead to undefined behavior, due to C++ Standard 5/4. So this really is a crappy exam question.
int arr[3]={10,20,30}; // obvious?
int *arrp = new int; // allocated memory for an int
(*(arr+1)+=3)+=5; // (1)
(arrp=&arr[0])++; // (2)
std::cout<<*arrp; // (3)
(1)
*(arr+1) is the same as arr[1], which means that *(arr+1)+=3 will increase arr[1] by 3, so arr[1] == 23 now.
(*(arr+1)+=3)+=5 means arr[1] is increased by another 5, so it will be 28 now.
(2)
arrp will pont to the address of the first element of arr (arr[0]). The pointer arrp will then be incremented, thus it will point to the second element after the entire statement is executed.
(3)
Prints what arrp points to: the second element of arr, meaning 28.
Well, remember that arrays can be interpreted as pointers
int arr[3]={10,20,30};
int *arrp = new int;
creates an array arr of three integers and an int pointer that gets assigned with a freshly allocated value.
Since assignment operators return a reference to the value that has been assigned in order to allow multi-assignment,
(*(arr+1)+=3)+=5;
is equivalent to
*(arr+1)+=3;
*(arr+1)+=5;
*(arr + 1) refers to the first element of the array arr, therefore arr[1] is effectively increased by eight.
(arrp=&arr[0])++; assigns the address of the first array element to arrp and afterward increments this pointer which now points to the second element (arr[1] again).
By dereferencing it in std::cout<<*arrp, you output arr[1] which now holds the value 20 + 3 + 5 = 28.
So the code prints 28 (and furthermore creates a memory-leak since the new int initially assigned to arrp never gets deleted)
I'll try to answer you by rewriting the code in a simpler way.
int arr[3]={10,20,30};
int *arrp = new int;
(*(arr+1)+=3)+=5;
(arrp=&arr[0])++;
std::cout<<*arrp;
=== equals ===
int arr[3]={10,20,30};//create array of 3 elements and assign them
int *arrp = new int;//create an integer pointer and allocate an int to it(useless)
//(*(arr+1)+=3)+=5;
arr[1] = arr[1] + 3;//arr[1] == arr+1 because it is incrementing the arr[0] pointer
arr[1] = arr[1] + 5;
//(arrp=&arr[0])++;
arrp = &arr[0];//point the integer pointer to the first element in arr[]
arrp++;//increment the array pointer, so this really is now pointing to arr[1]
std::cout<<*arrp;//just print out the value, which is arr[1]
I am assuming you understand pointers and basic c.