can someone please explain to me why this works. I thought arrays were static and couldn't expand, this piece of code defies my prior knowledge.
#include <iostream>
using namespace std;
int main(){
int test[10];
int e = 14;
for(int i = 0; i < e; i++){
test[i] = i;
cout << " " << test[i];
}
return 0;
}
This code outputs this:
0 1 2 3 4 5 6 7 8 9 10 11 12 13
So basically this program uses array spaces that shouldn't exist.
Tried setting 'e' as 15, doesn't work.
The array's size is fixed, it is not expanding, and going beyond its bounds is undefined behaviour. What you observed is one possible outcome of undefined behaviour (UB). You were unlucky that in this case the UB suggests a pattern consistent with the array expanding.
It's undefined behaviour. You still have only 10 ints allocated legally. Though it seems to work in this case, your program is ill-formed.
You basically write beyond the boundary of the memory allocated by your array, but C (and C++) is compiled directly to machine code (an opposite to "managed" code executed by virtual machine, like Java or .NET), so there is nothing between your program and OS which will verify if you access memory you have not explicitly asked for. Memory is allocated in some chunks, when a process is requesting some portion of memory from OS, it does not get that precise number of bytes, but may get slightly more. In your case instead of 40 bytes you got 56. Why you did not get 60 - depends on OS memory allocation and verification mechanism. What was the symptom of not working when e was set to 15 - program crash?
It is a runtime error and not a compilation error. The reason is fails at 15 and not 14 is of because once you reach position 15 you have hit memory that has been allocated to another pointer or application. It just so happens that indexes 11, 12 ,13 and 14 are contiguous memory locations that have not yet been malloc'ed
Related
I was just trying something and i was wondering how this could be. I have the following Code:
int var1 = 132;
int var2 = 200;
int *secondvariable = &var2;
cout << *(secondvariable+2) << endl << sizeof(int) << endl;
I get the Output
132
4
So how is it possible that the second int is only 2 addresses higher? I mean shouldn't it be 4 addresses? I'm currently under WIN10 x64.
Regards
With cout << *(secondvariable+2) you don't print a pointer, you print the value at secondvariable[2], which is an invalid indexing and lead to undefined behavior.
If you want to print a pointer then drop the dereference and print secondvariable+2.
While you already are far in the field of undefined behaviour (see Some programmer dude's answer) due to indexing an array out of bounds (a single variable is considered an array of length 1 for such matters), some technical background:
Alignment! Compilers are allowed to place variables at addresses such that they can be accessed most efficiently. As you seem to have gotten valid output by adding 2*sizeof(int) to the second variable's address, you apparently have reached the first one by accident. Apparently, the compiler decided to leave a gap in between the two variables so that both can be aligned to addresses dividable by 8.
Be aware, though, that you don't have any guarantee for such alignment, different compilers might decide differently (or same compiler on another system), and alignment even might be changed via compiler flags.
On the other hand, arrays are guaranteed to occupy contiguous memory, so you would have gotten the expected result in the following example:
int array[2];
int* a0 = &array[0];
int* a1 = &array[1];
uintptr_t diff = static_cast<uintptr_t>(a1) - static_cast<uintptr_t>(a0);
std::cout << diff;
The cast to uintptr_t (or alternatively to char*) assures that you get address difference in bytes, not sizes of int...
This is not how C++ works.
You can't "navigate" your scope like this.
Such pointer antics have completely undefined behaviour and shall not be relied upon.
You are not punching holes in tape now, you are writing a description of a program's semantics, that gets converted by your compiler into something executable by a machine.
Code to these abstractions and everything will be fine.
I have a piece of code:
#include <iostream>
using namespace std;
int main(){
char a[5][5] = {{'x','y','z','a','v'},{'d','g','h','v','x'}};
for(int i=0; i<2; i++){
for(int j = 0; j<6; j++)
{
cout << a[i][j];
}
}
return 0;
}
As you can see the first and second dimensions are or size 5 elements each. With the double for loop's I am just printing what is initialized for variable a.
The size of int "j", as it increases the output changes dramatically.
Why is this happen?
Does pointer is the solution to this? If yes how? If no what can we do to avoid run time errors caused by this incorrect access?
You might be treating this issue like an out-of-bounds error in Java, where the behavior is strictly defined: you'll get an ArrayIndexOutOfBoundsException, and the program will immediately terminate, unless the exception is caught and handled.
In C++, this kind of out-of-bounds error is undefined behavior, which means the compiler is allowed to do whatever silly thing it thinks will achieve the best performance. Generally speaking, this results in the compiler just blindly performing the same pointer arithmetic it would perform on array accesses that are in-bounds, regardless of whether the memory is valid or not.
In your case, because you've allocated 25 chars worth of memory, you'll access valid memory (in most environments, UB withstanding) at least until i * 5 + j >= 25, at which point any number of things could happen:
You could get garbage data off the stack
You could crash the program with a Segmentation Fault (Access Violation in Windows/Visual Studio)
The loop could refuse to terminate at the index you expect it to terminate.
That last one is an incredible bug: If aggressive loop optimization is occurring, you could get some very odd behavior when you make mistakes like this in your code.
What's almost certainly happening in the code you wrote is that that first point: though you allocated space for 25 chars, you only defined the contents of 10 of them, meaning any accesses beyond those first 10 will invoke a different kind of undefined behavior (access of an uninitialized variable), which the vast majority of the time, results in their values being filled in with whatever coincidentally was in that memory space before the variable was used.
I am new to C++. I am learning some basics.
I tried the below program and got a run time error Stack around the variable x was corrupted.
int x = 56;
int *ptr = &x;
ptr[1]=8;
cout << *ptr << endl;
But if i update the index in line 3 to 0, say ptr[0] = 8, I am not getting any run time error and the console shows 8 as the output.
I assume 2 digits in the integer variable x and thought pointer index will have 0 and 1 as valid values. Why ptr[1] is causing run tume error where as ptr[2], ptr[3] does not cause any run times error and simply shows 56 as o/p.
Can any one help me to understand what is really going on here. May be a better tutorial site as an add on would help me to understand more on this subject.
ptr[1] is actually the integer next to the variable pointed to by ptr. Writing to such memory means overwriting about anything. You may overwrite other variables. Or return addresses. Or stack frames. Or about anything else. Heck, you may overwrite ptr itself, depending on how variables on the stack are arranged.
Undefined behavior. Compilers are allowed to assume it doesn't happen.
Let see what you are doing here (Lets assume int is 4 bytes):
int x = 56;
int *ptr = &x;
ptr[1]=8;
cout << *ptr << endl;
<- 4 bytes->......(rest of the stack)
----------------
| x | |
----------------
^ ^
ptr[0] ptr[1]
So, pre[1] is writing to a memory location which does not yet exist. So, you are writing data out-of-bound.
Presumably you were expecting ptr[1] to mean the second byte in x. But that's not how pointer arithmetic works. The pointer is an int*, so arithmetic is performed in "chunks" of int-sizes. Therefore, ptr[1] is the non-existent integer "next to" x.
You could probably see this working by making ptr a char* instead, but be careful because this is real hackery and probably not a good idea unless you really know what you're doing.
A further misconception is your indication that the number of decimal digits in the human-readable representation of x's value has anything to do with the number of bytes taking up by x in memory; it doesn't.
#include <iostream>
using namespace std;
int main()
{
int a=50;
int b=50;
int *ptr = &b;
ptr++;
*ptr = 40;
cout<<"a= "<<a<<" b= "<<b<<endl;
cout<<"address a "<<&a<<" address b= "<<&b<<endl;
return 0;
}
The above code prints :
a= 50 b= 50
address a 0x7ffdd7b1b710 address b= 0x7ffdd7b1b714
Whereas when I remove the following line from the above code
cout<<"address a "<<&a<<" address b= "<<&b<<endl;
I get output as
a= 40 b= 50
My understanding was that the stack grows downwards, so the second answers seems to be the correct one. I am not able to understand why the print statement would mess up the memory layout.
EDIT:
I forgot to mention, I am using 64 bit x86 machine, with OS as ubuntu 14.04 and gcc version 4.8.4
First of all, it's all undefined behavior. The C++ standard says that you can increment pointers only as long as you are in array boundaries (plus one element after), with some more exceptions for standard layout classes, but that's about it. So, in general, snooping around with pointers is uncharted territory.
Coming to your actual code: since you are never asking for its address, probably the compiler either just left a in a register, or even straight propagated it as a constant throughout the code. For this reason, a never touches the stack, and you cannot corrupt it using the pointer.
Notice anyhow that the compiler isn't restricted to push/pop variables on the stack in the order of their declaration - they are reordered in whatever order they seem fit, and actually they can even move in the stack frame (or be replaced) throughout the function - and a seemingly small change in the function may make the compiler to alter completely the stack layout. So, even comparing the addresses as you did says nothing about the direction of stack growth.
UB - You have taken a pointer to b, you move that pointer ptr++ which means you are pointing to some unknown, un-assigned memory and you try to write on that memory region, which will cause an Undefined Behavior.
On VS 2008, debugging it step-by-step will throw this message for you which is very self-explanatory::
The following code
int x;
cin >> x;
int b[x];
b[5] = 8;
cout << sizeof(b)/sizeof(b[0]) << endl << b[5];
with x inputted as 10 gives the ouput:
10
8
which seems very weird to me because:
According to http://www.cplusplus.com/doc/tutorial/arrays/ we shouldn't even be able to initialize an array using a value obtained from cin stream.
NOTE: The elements field within square brackets [], representing the number of elements in the array, must be a constant expression, since arrays are blocks of static memory whose size must be determined at compile time, before the program runs.
But that's not the whole story! The same code with x inputted as 4 sometimes gives the output
Segmentation fault. Core dumped.
and sometimes gives the output:
4
8
What the heck is going on? Why doesn't the compiler act in a single manner? Why can I assign a value to an array index that is larger than the array? And why can we even initialize an array using variable in the first place?
I initially mentioned this as a comment, but seeing how no one has answered, I'm gonna add it here.
What you have demonstrated above is undefined behavior. It means that you can't tell what will the outcome be. As Brian adds in the comments, it will result in a diagnostic message (which could be a warning). Since the compiler would go ahead anyway, it can be called UB as it is not defined in the standard.