Why not causing a segmentation error? [duplicate] - c++

This question already has answers here:
Accessing an array out of bounds gives no error, why?
(18 answers)
Closed 6 years ago.
#include <iostream>
using namespace std;
int main(){
int a[3], no;
cout << "Index Value\n";
for(int i = 0; i < 100; i++){
cin >> no;
a[i] = no;
cout << i << "\t" << a[i] << endl;
}
return 0;
}
Here I initialized a[ 3 ]. In for loop, I'm feeding input 100 times to a[ ], exceeding the indices of [ 3 ].
Why don't it give segmentation error right after when i equals 4.
Input
1 2 3 4 5 6 7
Output
Index Value
0 1
1 2
2 3
4 0
5 5
6 6
7 7
Output is wrong when Index equals 4. Printed 0 . Expected 4

Unfortunately for the debugging programmer, C and C++ programs don't usually segfault when you write past the end of an array. Instead it will usually silently write over whatever the pointer arithmetic as up to -- if the OS allows it. This often overwrites other variables or even program code, causing confusing and unpredictable errors.
I have used the word "usually" here because according to the standards this is "undefined behaviour" -- that is, the compiler and runtime can do anything they like.
When developing and testing, it can be very useful to use a library such as electricfence, which puts extra checks into memory operations and would make your program fail in the way you expect.

Related

User input can exceed size of array, but eventually crashes, why? [duplicate]

This question already has answers here:
Undefined, unspecified and implementation-defined behavior
(9 answers)
Closed 5 years ago.
I allow the user to enter the number of iterations for my array. I am trying to understand what happens When you exceed the max size of 10 and enter a number higher than that, such as 255. The user can then enter in numbers for each iteration. The program allows for a couple extra inputs, but crashes at around 12 or 13. Why is this happening? Why can't the program allow for the 255 iterations specified? I believe it has to do something with the way memory is referenced in c++, but I am not sure.
#include <iostream>
using namespace std;
int main()
{
int nums[20] = { 0 };
int a[10] = { 0 };
cout << a << endl;
cout << nums << endl;
cout << "How many numbers? (max of 10)" << endl;
cin >> nums[0];
for (int i = 0; i < nums[0]; i++)
{
cout << "Enter number " << i << endl;
cin >> a[i];
}
// Output the numbers entered
for (int i = 0; i < 10; i++)
cout << a[i] << endl;
return 0;
}
}
If this program is run and we enter 255 for how many numbers, and 9 for every single number, then the program does this:
How many numbers? (max of 10)
255
Enter number 0
9
Enter number 1
9
Enter number 2
9
Enter number 3
9
Enter number 4
9
Enter number 5
9
Enter number 6
9
Enter number 7
9
Enter number 8
9
Enter number 9
9
Enter number 10
9
Enter number 11
9
Enter number 12
9
//(program crashes somewhere around here.)
This:
int a[10] = { 0 };
cin >> a[i];
Is only valid if i is between 0 and 9. Any value outside of that is "undefined behavior" which means the program could do anything. Including not crashing for the first couple violations then crashing later. Including crashing immediately. Including never crashing. Or anything else. It's undefined.
What you are doing in your code is that you are moving outside the valid range of the array a[]. This moves on to undefined behaviour, as you experienced. Even going to a[10] is incorrect, even if your program crashed after you entered the 12th number. The very meaning of undefined behaviour is that the kind of error will differ from machine to machine; another machine may take up to a[16] before crashing, or one may simply, and rightly, stop and crash at a[10]. That is why it is called undefined behaviour; knowing that it will crash sooner or later, but not seeing a fixed pattern.
This undefined behaviour stems from your computer's memory. Everytime you rerun your program, your array is allocated a different block of memory in your local memory. This means that the memory blocks around could be filled or unfilled. As a result, if your code is faulty and you extend an array's index out of its range, it may works for the next few memory bytes if they are empty and accessible. However, as soon as they reach a full byte, or if that memory byte is inaccessible, then it will lead the program to crash. Also, since this array's location in memory can change as the program is rerun, "how far" it will go before crashing will depend entirely on the neighbouring bytes of memory.
This is a lot of theory, so if I got something wrong here by accident, please let me know. For further reading, you can visit Wikipedia
The simple answer to this is that your program is trying to write to bits that you have not allocated. It will do this until it tries to write to a bit that another process is using. This is what is crashing it, because this bit is unavailable. You just appear to be hitting "already in use" around 12 or 13.

Undefined Behavior quirk: reading outside a buffer causes a loop to never terminate?

I wrote a very trivial program to try to examine the undefined behavior attached to buffer overflows. Specifically, regarding what happens when you perform a read on data outside the allocated space.
#include <iostream>
#include<iomanip>
int main() {
int values[10];
for (int i = 0; i < 10; i++) {
values[i] = i;
}
std::cout << values << " ";
std::cout << std::endl;
for (int i = 0; i < 11; i++) {
//UB occurs here when values[i] is executed with i == 10
std::cout << std::setw(2) << i << "(" << (values + i) << "): " << values[i] << std::endl;
}
system("pause");
return 0;
}
When I run this program on Visual Studio, the results aren't terribly surprising: reading index 10 produces garbage:
000000000025FD70
0(000000000025FD70): 0
1(000000000025FD74): 1
2(000000000025FD78): 2
3(000000000025FD7C): 3
4(000000000025FD80): 4
5(000000000025FD84): 5
6(000000000025FD88): 6
7(000000000025FD8C): 7
8(000000000025FD90): 8
9(000000000025FD94): 9
10(000000000025FD98): -1966502944
Press any key to continue . . .
But when I fed this program into Ideone.com's online compiler, I got extremely bizarre behavior:
0xff8cac48
0(0xff8cac48): 0
1(0xff8cac4c): 1
2(0xff8cac50): 2
3(0xff8cac54): 3
4(0xff8cac58): 4
5(0xff8cac5c): 5
6(0xff8cac60): 6
7(0xff8cac64): 7
8(0xff8cac68): 8
9(0xff8cac6c): 9
10(0xff8cac70): 1
11(0xff8cac74): -7557836
12(0xff8cac78): -7557984
13(0xff8cac7c): 1435443200
14(0xff8cac80): 0
15(0xff8cac84): 0
16(0xff8cac88): 0
17(0xff8cac8c): 1434052387
18(0xff8cac90): 134515248
19(0xff8cac94): 0
20(0xff8cac98): 0
21(0xff8cac9c): 1434052387
22(0xff8caca0): 1
23(0xff8caca4): -7557836
24(0xff8caca8): -7557828
25(0xff8cacac): 1432254426
26(0xff8cacb0): 1
27(0xff8cacb4): -7557836
28(0xff8cacb8): -7557932
29(0xff8cacbc): 134520132
30(0xff8cacc0): 134513420
31(0xff8cacc4): 1435443200
32(0xff8cacc8): 0
33(0xff8caccc): 0
34(0xff8cacd0): 0
35(0xff8cacd4): 346972086
36(0xff8cacd8): -29697309
37(0xff8cacdc): 0
38(0xff8cace0): 0
39(0xff8cace4): 0
40(0xff8cace8): 1
41(0xff8cacec): 134514984
42(0xff8cacf0): 0
43(0xff8cacf4): 1432277024
44(0xff8cacf8): 1434052153
45(0xff8cacfc): 1432326144
46(0xff8cad00): 1
47(0xff8cad04): 134514984
...
//The heck?! This just ends with a Runtime Error after like 200 lines.
So apparently, with their compiler, overrunning the buffer by a single index causes the program to enter an infinite loop!
Now, to reiterate: I realize that I'm dealing with undefined behavior here. But despite that, I'd like to know what on earth is happening behind the scenes to cause this. The code that physically performs the buffer overrun is still performing a read of 4 bytes and writing whatever it reads to a (presumably better protected) buffer. What is the compiler/CPU doing that causes these issues?
There are two execution paths leading to the condition i < 11 being evaluated.
The first is before the initial loop iteration. Since i had been initialised to 0 just before the check, this is trivially true.
The second is after a successful loop iteration. Since the loop iteration caused values[i] to be accessed, and values only has 10 elements, this can only be valid if i < 10. And if i < 10, after i++, i < 11 must also be true.
This is what Ideone's compiler (GCC) is detecting. There is no way the condition i < 11 can ever be false unless you have an invalid program, therefore it can be optimised away. At the same time, your compiler doesn't go out of its way to check whether you might have an invalid program unless you provide additional options to tell it to do so (such as -fsanitize=undefined in GCC/clang).
This is a trade off implementations must make. They can favour understandable behaviour for invalid programs, or they can favour raw speed for valid programs. Or a mix of both. GCC definitely focuses greatly on the latter, at least by default.

C++ for loop and do-while loop of a single dimensional array gives questionable output [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I am taking a course on edx.org Introduction to C++ by Microsoft. I get unwanted output when looping through a single dimensional array. The code is below.
<#include <iostream>
int main() {
int arrayName[10] = { 1,2,3,4,5,6,7,8,9,10 };
for (int i = 1; arrayName[i] <= 20; i++) {
std::cout << i << std::endl;
}
The output of this is:
1
2
3
4
5
6
7
8
9
10
11
Where does the 11 come from? And, if I make i=0, it also prints a 0. How does it print more than 10? And, when I try to change arrayName[10] to arrayName[9], I get a compiler error that there are too many initialized values:
int arrayName[10] = { 1,2,3,4,5,6,7,8,9,10 };
do {
std::cout << i << std::endl;
i++;
} while (arrayName[i] < 5);
The output is:
12
13
14
15
16
17
18
That do-while loop outputs 7 integers that I did not specify to be included in the arrayName[] array.
I don't know what I am doing wrong or what I am not understanding.
Please help. Thank you!
First, note that arrays in c++ start at index 0. So in int arrayName[3] = {10, 42, 88}; then arrayName[1] is 42, not 10. That means the last element in this array is int arrayName[2]. There is no element at index 3.
Your array only contains 10 elements (indices 0 to 9). The standard does not specify what happens when you access an element past the end of an array, anything can happen. In your case, arrayName[10] and arrayName[11] happens to give you something less than or equal to 20, and then arrayName[12] gave you something greater than 20, ending the loop. If you try it on another computer, or even at a different time, the results will vary. It might also crash (this is the best case scenario).
See this answer for more information on undefined behavior.
I finally found this: Correct way of loop through the C++ arrays, answer by https://stackoverflow.com/users/1619294/mark-garcia.
Changed my code to:
std::cout << "Looping through arrayName3 with std::array and letting the compiler determine how many objects to print:" << std::endl;
// Need to #include <array>
std::array<int, 10> arrayName3 = { 1,2,3,4,5,6,7,8,9,10 };
for (const auto& i : arrayName3) // Range-for
{
std::cout << i << std::endl;
}
The output was what I wanted:
1
2
3
4
5
6
7
8
9
10
This let's the compiler know it is deciding what to output. It would be great to know how to change this to control how many indices to loop through.

C++ array gives me garbage value [duplicate]

This question already has answers here:
How do I use arrays in C++?
(5 answers)
Closed 7 years ago.
I just started learning c++ and came to Arrays. So what I want to do is perform some function on the array that was passed in function. So for this I tried small example
#include <iostream>
using namespace std;
void printArray(int data[]){
cout<<"len is :"<< sizeof(data)<<endl;
for(int i = 0 ;i<sizeof(data); i++){
cout<<data[i]<<" ";
}
cout<<endl;
}
int main() {
int data[] = {1,2,3,4,5,6};
printArray(data);
cout<<"in main :"<<sizeof(data)<<endl;
for(int i = 0 ;i<sizeof(data); i++){
cout<<data[i]<<" ";
}
return 0;
}
And Following is the output I obtained from the code
len is :8
1 2 3 4 5 6 738192384 -1126994503
in main :24
1 2 3 4 5 6 738192384 -1126994503 0 0 -1061892411 32677 0 0 -1665163256 32766 0 1 4196851 0 0 0 463403231 1946389667
I am not understanding where the process goes wrong. or is some thing in my code that make these weird changes to happen. and also the sizeof() is giving two values for the same array.Correct me where I am wrong anywhere.
I am using Eclipse software with c++ plugin added.
Thanks in advance for help!!
sizeof doesn't work if you pass an array to the function in this fashion. Try passing the size with the array or pass the begin and end pointers of the array.
If you don't mind templates, you can pass the array by reference:
template<unsigned length>
void printArray(int (&data)[length]) {
//length is the length of data
}

Modulo gives impossible value

I want a table of four values between 1 to 6.
I'm using: rand() % 6 + 1;
This should give values between 1 and 6.
Except if rand() generates the value 0.
I keep getting 7's. I don't want any 7's
What is the range of rand? How I prevent it from generation any 0 values?
Alternative solutions are quite welcome.
My teacher gave us the clue of using "random".
We use Borland C++ Builder 5 at school.
I am using Dev-C++ 5.3.0.3 at home.
I find there are a few differences to how they work, which I find strange..
I can't use random(), it gives me not declared in scope...
int main (){
int I;
int Fasit[3];
srand (time(NULL) );
for(I=0; I<4; I++) {
Fasit[I]=rand() % 6 + 1;
}
std::cout << Fasit[0] << " " << Fasit[1] << " " << Fasit[2] << " " << Fasit[3] << " ";
return 0;
}
Some values I get:
2 6 1 7
5 2 1 4
5 2 1 4
5 2 1 4
1 3 1 6
5 3 3 7
5 3 3 7
5 3 3 7
7 shouldn't be possible, should it?
PS: I know my print is ham fisted, I will make it a bit more elegant once the number generation works.
Consdier these lines:
int Fasit[3];
for(I=0; I<4; I++) {
Fasit[I]
You declare an array of three entries, which you write to four times.
Try your program again, but with:
int Fasit[4];
You only have 3 elements in Fasit[3]; When you write to Fasit[3], you are in the realm of undefined behavior, which in this case manifests it self with apparent contradiction.
Fasit[3] allows you to access only Fasit[0], Fasit[1], and Fasit[2].
Accessing Fasit[3], either for reading and writing, is undefined behavior. Your code is both writing and reading to Fasit[3] :-). The program is accessing the array out-of-bound. Fix it!
As to why 7 is printed, that is just coincidence. Note that Fasit[0-3] is always printed in the range 1-6 as you expected.
See also:
Array Index out of bound in C
Bounds checking
int Fasit[3];
You are creating an array of size 3, which can be accessed with indexes 0, 1 or 2 only.
You are writing and reading Fasit[3], which has an undefined behaviour. When a behaviour is undefined, you are bound to obtain weird results. This is it.