Explanation of undefined behaviour, and whether it's truly undefined - c++

I have dynamically allocated memory for an array of 5 elements, then tried to print its elements to std::cout, which should have left me with a fairly straightforward result. I got something else instead, and it left me with some questions.
My code:
#include <iostream>
int main()
{
int *array = new int[5];
int array_size = sizeof(array);
for (int index = 0; index < array_size; index++) {
std::cout << array[index] << "\n";
}
std::cout << "\nThe array is " << array_size << " elements long.";
return 0;
}
This is what this resulted in:
0
0
0
0
0
0
132049
0
Now, I understand this isn't how things are done, but such a result has left me with several questions.
Why is the size of the array 8, and not 5? Originally, I thought that it's becase the memory according to powers of 2, but I have a feeling I'm wrong.
What's with 132049?

Your code has two problems, each of them leading to undefined behavior.
First, sizeof(array) is the size of the pointer in bytes, not the array. On your machine, a pointer happens to take 8 bytes. This causes out-of-range access, which is undefined behavior.
Second, new int[5] gives you an uninitialized array. Accessing the value of an uninitialized object is undefined behavior.
To fix these problems, first note that the size of an array returned by new is lost. sizeof cannot help you. You can only provide this information yourself. Then you have to initialize the elements.
#include <iostream>
int main()
{
int *array = new int[5]{}; // note: initialization
int array_size = 5;
for (int index = 0; index < array_size; index++) {
std::cout << array[index] << "\n";
}
std::cout << "\nThe array is " << array_size << " elements long.";
return 0;
}
This is code is guaranteed to print
0
0
0
0
0
The array is 5 elements long.
(As long as there is enough memory and output succeeds)

Related

Where is the array getting that value from?

So here's a simple program that just search for two numbers in an array that sum up to a certain value k
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int main()
{
unordered_set<int> hashtable;
int k =7;
int arr[5] = {1, 2, 3, 4, 5};
int s = sizeof(arr);
for (int i =0; i<s; i++){
if( hashtable.find(k - arr[i])!= hashtable.end() )
{
cout << arr[i] << endl;
cout<< "found one " << arr[i] << " and "<< k-arr[i]<< endl;
} else {
hashtable.insert(arr[i]);
}
}
return 0;
}
And here's the out put, I am getting
4
found one 4 and 3
5
found one 5 and 2
7
found one 7 and 0
7
found one 7 and 0
Am I missing something?
You access the array outside of its bounds. The behaviour of the program is undefined.
sizeof does not yield the number of elements in an array. It yields the size of an object in bytes. When the size of the element is more than one byte - and int is more than one byte on most systems - then the number of bytes in the array is more than the number of elements.
A correct way to get the number of elements in an array is to use std::size:
int s = std::size(arr);
Since you use only arr[i] and not i itself, you can write for (auto a : arr). This will respect the array bounds, you don't need to calculate the maximum index. Hence, it avoids the wrong calculation (which the other answers fix)
Maybe there are other ways to get the size of an array but for now this will do :
int s = sizeof(arr)/sizeof(arr[0]);

c++ array of pointers and memory address allocation

Can someone explain how an array of pointers implementation of c++ dynamically?
Is the below code correct?
If so,
int *ptr[5];
for (int i = 0; i < 5; i++)
{
int size = 2;
ptr[i] = new int [size] ;
//*(ptr + i) = new int[size]; this is the same as above line
cout << &ptr[i] << endl; ----------> line 1
cout << ptr[i] << endl; -----------> line 2
}
What is actually printing in line 1 and 2 ?
this is the addresses i get for line 1
0x7fff88f805d0
0x7fff88f805d8
0x7fff88f805e0
0x7fff88f805e8
0x7fff88f805f0
this is the addresses I get for line 2
0x55f946348ef0
0x55f946349330
0x55f946349360
0x55f946349390
0x55f9463493c0
Can somebody explain this whole mess of pointer arrays.
The picture provides a graphical explanation to the problem if anyone gets
confused with the array of pointers concept with dynamically allocating the array of pointers to new int or any other type array
int *ptr[2]; // statically declared pointer array stack
int p [2];
for (int i = 0; i < 2; i++)
{
int size = 2;
ptr[i] = new int[size];
cout << i << " array of int " << endl;
//*(ptr + i) = new int[size];
for (int j = 0; j < size; j++)
{
cout << "value : " ;
cout << *(ptr[i] + j) ; // <------- this should give 0's as value
//cout << (ptr[i])[j] ; <------ same thing
cout << " address :";
cout << ptr[i] + j << endl; //<----- these are in order as well since it's an array of type int
}
}
0 array of int
value : 0 address :0x564c9ede32c0
value : 0 address :0x564c9ede32c4
value : 0 address :0x564c9ede32c8
1 array of int
value : 0 address :0x564c9ede32e0
value : 0 address :0x564c9ede32e4
value : 0 address :0x564c9ede32e8
I am assuming you want to perform operation on dynamic array like adding element and printing;
Remember:In int *ptr=new int[5]; sizeof(ptr) is 8 bytes on stack memory and array will be stored in heap memory.
We will fetch the element via pointer ptr and every element will be fetched as per type of array (say int ) then ptr will go to 0th index element and read the data of it as int type (only 4 bytes as int is of 4 byte generally) and move to next index till end.
Look into code below:
#include <iostream>
using namespace std;
int main() {
int *ptr=new int[5]; //let size = 5
for(int i=0; i<5;i++){
cin>>ptr[i];
}
for(int i=0; i<5;i++){
cout<<&ptr[i]<<":"; //this will print every element's address per iteration
cout<<ptr[i]<<endl; //this will print every element as per input you gave
}
delete []ptr; //remember it's not delete ptr ask if required
return 0;
}
Now See the the output and dry run yourself you can understand
Output
0x556999c63e70:1
0x556999c63e74:2
0x556999c63e78:3
0x556999c63e7c:4
0x556999c63e80:5
Benefit of dynamic array is you can create dynamic sized array by taking size input as per user choice pass that variable is size of dynamic array
i.e you can change above size=5 to 'N' a variable one .
I think this might help you else you can ask for any further clarification.

Characters duplicate in a multidimensional array

I have created an empty char multidimensional array, but when I try to change a specific value, it sometimes duplicates to another space in the array.
Example:
#include <iostream>
using namespace std;
char arr[2][2] = { 0 };
int main ()
{
arr[2][0] = 'A';
for(int i = 0; i < 3; ++i)
{
for(int j = 0; j < 3; ++j)
{
cout << "arr[" << i << "][" << j << "] = " << arr[i][j] << endl;
}
}
}
Output:
arr[0][0] =
arr[0][1] =
arr[0][2] =
arr[1][0] =
arr[1][1] =
arr[1][2] = A
arr[2][0] = A
arr[2][1] =
arr[2][2] =
The character A should only appear in [2][0] but it also appears in [1][2].
This happens only in these spaces:
[1][0], [2][0], [0][2], [2][2]
I was able to recreate this with a bigger array, but I can't say the specific values.
I have tried defining inside the main() function but it created another problem, random characters started appearing in random locations of the array.
I tried initializing the array with char arr[2][2] = { 0 }, but it didn't help.
When you declare char arr[2][2] = { 0 };, that's a 2x2 array. Which means it's indices go from 0 to 1. You're writing into index 2, which is outside of array bounds.
There is probably some memory bashing happening.
When you declare an array as char arr[2][2] = { 0 }; array of two arrays of size two of char. Which means 4 char elements.
You can access them as
arr[0][0];
arr[0][1];
arr[1][0];
arr[1][1];
For your code to work you need to buff up the size of the array to char arr[3][3] = { 0 };
To answer your question why are they duplicated.
The memory continues when you allocate char arr[2][2] it will allocate space for 4 elements and it might be the same as char arr[4].
When you try to access an element out of the bounds of your array the behavior is undefined at it resulted in accessing the memory of the second array.
That's because you're going past your array. An array of char arr[2] only goes from 0 to 1 (that's 2 values). Similarly, for your arr[2][2] you can also only use 0 and 1 as array index.
Try this instead:
char arr[3][3] = { 0 };
Now the array index can go from 0 to 2.

For loop with an array

#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
int a[5];
for (int i = -1; i < 7; i++)
cout << i << " " << setw(2) << a[i] << endl;
}
So I'm trying to figure out why this won't work. If i take out a[i] it works, but if i leave it in, the for loop goes from -2 until the 1000's which is obviously not right. Is it because a[i] is not bound to the parameters of the for loop (i < 7)? I'm not really sure I understand.
EDIT As many of you have explained it was a matter of uninitializing the array and using bounds outside of the array (e.g -2). It was not something I thought of, nor found when searching for why this was happening.
First, as marcadian pointed out, the array a is not initialized, so values in the array are completely random.
Also, the size of the a array is 5, meaning that you can access between indexes 0 and 4 inclusive.
However, in your loop, you try to access at index -1, and index 6. Attempting to write and read at invalid indexes ( such as -1 and 6, in this case ) is undefinded behavior ( it can crash with a segmentation fault, or corrupt other variables, which can make debugging process very hard ... )
A way to avoid buffer overrun like you did is to use std::array STL container, like this :
std::array<int, 5> a;
//Access elements using the method 'at()', it has bound checking
a.at(0); // 0 is a valid index
//a.at(-1); // -1 is not a valid index, it will crash ( at least in debug mode )
//a.at(6); // 6 is also not a valid index
The std::array STL container does the same things normal array does, but provides useful methods
You're printing out random value in memory because variable a is not initialized. Uninitialized variable has random value in memory. What are you trying to do?
in computers an array is really just a given number of values, starting at array[0], and ending at array[n].
int a[5]; statically allocates space for 5 integers on the stack, starting at a[0], and ending at a[4].
Try this iteration instead:
for (int i = 0; i < 4; i++)
In addition to not initializing the array, a, the indices you would be using to access its elements are out of bounds. C++ uses zero-indexing - you could try, for instance:
int main() {
int a[] = {1, 2, 3, 4, 5};
for (int i = 0; i < 5; i++) {
cout << i << " " << a[i] << endl;
}
}
Output would be:
0 1
1 2
2 3
3 4
4 5

C++ What's wrong with my array/loop?

I've just started learning C++ so I'm fairly sure the answer may be a simple one. As a test I'm just setting up an array and then wanting to print out the array by looping through it.
My code is below. It prints out my array as expected but then prints out a load of other numbers below it. What are these numbers and where are they coming from? I suspect that 'sizeof' isn't the best to use. All of the examples i've found are alot more complicated than I need. In any case I am interested to understand the extra numbers. Any insight available?
int age[4];
age[0]=23;
age[1]=34;
age[2]=65;
age[3]=74;
for (int i = 0; i <= sizeof(age); i++)
cout << age[i] << endl;
return 0;
...output:
23
34
65
74
4
2147307520
0
2293608
4198582
1
3084992
3085608
-1
2293592
1980179637
-725187705
-2
sizeof gives the size of an object in bytes. If the array elements are larger than one byte (as int usually is), the number will be larger than the array size.
One way to get the number of elements in an array is to divide by the size of an element:
for (size_t i = 0; i < sizeof(age)/sizeof(age[0]); i++)
std::cout << age[i] << '\n';
(note that you also need < rather than <=, or you'll still step off the end).
Another way is to pass a reference to the array to a function template, instantiated for the array size:
template <typename T, size_t size>
void print(T (&array)[size])
{
for (size_t i = 0; i < size; ++i)
std::cout << array[i] << '\n';
}
print(age);
Yet another way is to use a std::vector or std::array instead of a plain array:
std::array<int, 4> age;
age[0]=23;
age[1]=34;
age[2]=65;
age[3]=74;
for (size_t i = 0; i < age.size(); ++i)
std::cout << age[i] << '\n';
sizeof(age) == sizeof(int) * number_of_elements ==>
number_of_elements = sizeof(age) / sizeof(int)
Then your code becomes:
for (int i = 0; i < sizeof(age)/sizeof(age[0]); ++i)
cout << age[i] << endl;
In C++ you may write a function to calculate the size for you(doesn't work with dynamic arrays):
template <class T, std::size_t size>
std::size_t array_size( T(&arr)[size] )
{
return size;
}
If you are up to C++11, you could go with for-each loop:
for(int element : age){
....
}
Also, free-function form of std::begin and std::end can do the job:
for(auto b = std::begin(age); b != std::end(age); ++b){
....
}
Sould be i < 4 because sizeof(age) is 16 on a 32 bits machine.
sizeof(age) is the number of bytes of age, not the number of elements.
Divide it by the size of an element of age to get that:
for (int i = 0; i < sizeof(age) / sizeof(*age); i++)
cout << age[i] << endl;
Note: for dynamic arrays, you have to store the size of the array separately:
std::size_t size = 4; // size_t corresponds to maximum size an array can hold
int* age = new int[size];
for (int i = 0; i < size; i++)
cout << age[i] << endl;
The other numbers are garbage past the end of the array.
age[10] is undefined behavior, which is essentially garbage numbers.
Sizeof is age array is 16 bytes I.e. Sizeof(int) * 4. You need array length.
Since sizeof(age) returns 16, you have your 4 values plus 12 ones whose value comes from the memory that is right after your array. Values in those memory segment is random, depending on what has been stored there right before you launched your program. If you used a memory check tool, you would have had an error since this memory is probably not allocated for your program.
As the other ones said, you should probably giving the exact number of element in your array as an additional variable.
const int COUNT = 4;
int age[COUNT];
age[0]=23; age[1]=34; age[2]=65; age[3]=74;
for (int i = 0; i < COUNT; ++i)
{
cout << age[i] << endl;
}