Why am I getting different values in c++? - c++

I am getting different values for the a variable which is an int.
Although I know I am not initializing it, the value changes from 32767 32766 32765 and 32764 for variable a (with code version 1) and its always 0 with code version 2.
I know I don't have to leave variables uninitialized, just asked this question to see if anybody knew what is happening behind the scenes at runtime, I am using gcc .
whith code version 1
#include <iostream>
int main()
{
int a;
int *b = new int; // <----- this line
std::cout<<a<<std::endl;
std::cout<<*b<<std::endl;
return 0;
}
whith code version 2
#include <iostream>
int main()
{
int a;
std::cout<<a<<std::endl;
int *b = new int; // <----- same line moved here
std::cout<<*b<<std::endl;
return 0;
}

You read uninitialized memory. This is undefined behavior. That means the C++ language rules give literally no guarantee what happens when you run this code, at all. You may see the values you observed, nothing at all, crash your PC or set your house on fire. All equally legal outcomes of running this code.
In practice this will only print unpredictable garbage values in the range of int of course, dependent on what just happens to be left over in your memory and do nothing interesting.
Proof from the standard (N4140) for the non-believers:
When storage for an object
with automatic or dynamic storage duration is obtained, the object has an indeterminate value, and if
no initialization is performed for the object, that object retains an indeterminate value until that value is
replaced (5.17). [ Note: Objects with static or thread storage duration are zero-initialized, see 3.6.2. —
end note ] If an indeterminate value is produced by an evaluation, the behavior is undefined except in the
following cases:
[8.5 (12)], emphasize mine, the exceptions following this don't apply.

It's an unchecked coincidence in a highly complex system.
That may be the best answer you'll get regarding why uninitialized memory in your computer is showing you the pattern you see.
See also...

The c++ statement new int allocates memory from the heap but it doesn't initialize it. So whatever was on the heap or memory from before is being read. You have to do int *b = new int(0) to initialize what b is pointing to with 0.

Related

The segmentation fault error that I cannot understand [duplicate]

This question already has answers here:
Where exactly does C++ standard say dereferencing an uninitialized pointer is undefined behavior?
(7 answers)
Closed 4 years ago.
#include <iostream>
using namespace std;
int main() {
int *a;
int *b;
int c=12;
a=&c;
*b=*b;
cout << *b << endl;
}
The above code works fine, but the following code returns a segmentation fault error
#include <iostream>
using namespace std;
int main() {
int *a;
int *b;
int c=12;
//a=&c;
*b=*b;
cout << *b << endl;
}
Why?
gcc (Ubuntu 8.2.0-7ubuntu1) 8.2.0
Here's a step-by-step breakdown of what your code is doing:
int *a;
int *b;
This declares two pointers to int named a and b. It does not initialize them. That means that their values are unspecified, and you should expect them to be complete garbage. You can think of them as "wild" pointers at this moment, which is to say that they don't point to valid objects, and dereferencing them will cause Undefined Behavior and introduce a plethora of weird bugs, if not a simple crash.
int c=12;
This creates a simple local variable c of type int, which is initialized, with a value of 12. If you hadn't initialized it, as in int c; then it would also be full of garbage.
a=&c;
This snippet sets the pointer a to point to c, which is to say that the address of c is assigned to a. Now a is no longer uninitialized, and points to a well-defined location. After this, you can safely dereference a and be assured that there is a valid int at the other end.
*b=*b;
Here, you are dereferencing b, which means that you are reaching into your programs memory to grab whatever is pointed to by b. But b is uninitialized; it is garbage. What is it pointing to? Who knows? To read from the address it points to is like Russian roulette, you might kill your program immediately if you get really unlucky and the Operating System or runtime environment notices you doing something that's obviously wrong. But you also might get away with it, only for weird and unpredictable bugs to emerge later. This weirdness and unpredictability is why a good C++ programmer avoids Undefined Behavior at all costs, and ensures that variables are initialized before they are used, and makes sure that pointers are pointing to valid objects before dereferencing them.
Why does there appear to be a difference depending on a=&c;?
As to why your program apparently crashes or doesn't crash depending on how you initialize the other pointer, the answer is that it doesn't matter. In both cases, you're causing Undefined Behavior; you are breaking the language's rules and you should not expect the language to behave correctly for you thereafter, and all bets are off.
"*b=*b" - Is broken code. b is uninitialised, so you are dereferencing an uninitialised pointer. That's Undefined Behaviour. The program is broken and has no meaning according to the standard and the compiler is allowed to generate whatever code it feels like (no diagnostic required).

Moving pointer with Dynamic Memory C++

this is my first question in this forum, sorry my bad english.
I have a question about pointers and dynamic memory in c++.
Example, this code:
#include <iostream>
using namespace std;
int main(int argc, char const *argv[])
{
int *a = new int;
for (int i = 0; i < 5; i++)
cout << a++ << endl;
return 0;
}
Output:
0x11d4c20
0x11d4c24
0x11d4c28
0x11d4c2c
0x11d4c30
My question, is why can I move more than that 'single' block of memory that I created with new.
What is a pointing to?
Same occurs with new int[], even if I specific the size:
#include <iostream>
using namespace std;
int main(int argc, char const *argv[])
{
int *a = new int[2];
for (int i = 0; i < 5; i++)
cout << a++ << endl;
return 0;
}
Output:
0x2518c20
0x2518c24
0x2518c28
0x2518c2c
0x2518c30
Again, what is happening?
What is a pointing to?
Does all of this mean I'm violating memory?
a is an int*, not an int. What you are printing is actually the pointer, i.e. the memory address of the pointed object. Use the dereference operator * whenever you want to modify the pointed value, i.e.
cout << (*a)++ << endl;
NB: Likewise, you can get a pointer to an int using the reference operator, &, not to be mixed up with a reference (e.g. a int& type).
This may print 0 1 2 3 4. may because you are not initializing the new int created in dynamic memory. This means reading from *a (dereferenced a) is undefined behavior, which means your program may misbehave. You have to change your line using new:
int *a = new int();
This will initialize *a to 0 and now 0 1 2 3 4 will be printed correctly.
Note that int *a = new int[2]; does create a dynamic array of 2 entries in dynamic memory, which means *(a + 1) can be used as well (as if it was a regular array). It does not initialize *a to 2.
Do remember to delete a; when you've done using it. In a real application, you could get a memory leak if you don't - i.e. your program would still use memory it doesn't need anymore. Caution, when you have to delete a dynamically-allocated array (i.e. new int[2]), you need to use delete[] a; instead, or you will trigger undefined behavior.
You may also use a unique_ptr (or a shared_ptr) in C++11 as an alternative to this kind of memory allocation, i.e. :
#include <memory>
// ...
std::unique_ptr<int> a = std::make_unique<int>(0);
Thanks to this solution, you do not need to delete a because the unique_ptr will do this for you, when itself dies (i.e. out of the scope, here).
Edit: Bonus:
0x2518c20
0x2518c24
0x2518c28
Why is the number incremented by 4 if you just used ++?
Using ++ on an address will actually increment it by sizeof(T), which here is sizeof(int) and not 1. This explains why you can, as previously stated, use *(a + 1) if you used new int[2].
i think that it is ,because a points to an integer , the size of an integer is 4 bytes (sizeof(int) == 4) after executing a++ ,a points to the next integer,try char *a, and a++ to be more sure
It is legal to point at an object or the spot right after an object. A new int[2] creates two adjacent objects (in an array) and returns a pointer to the first one.
So yes, what you did above is not permitted. The behaviour of adding 5 to a pointer to a single object is not defined by the C++ standard; the compiler can generate assembly that does anything at all.
As it happens, on a flat memory architecture, pointers are basically unsigned integers. And incrementing a pointer by 1 is just incrementing it by the size of the pointed-to object.
So what often happens is you just get pointers to whatever happens to be there.
Now this is not guaranteed and should not be relied upon. Many of the rules of C++ that make actions undefined permit certain optimizations to occur over the "naive" mapping you might think the compiler does. For example, pointers to short can never point to an int and change its value in a defined way, which means if a function has both an int and short pointer it can assume that a write to the short does not modify the int.
The naive "write to the two words in an int" method of using shorts can work, then not work for seeming no reason, because the behaviour was undefined and the compiler was free to optimize assuming it could not happen.
In short, your actions are not legal, the behaviour you got is not surprising, but you can never rely on it.
Pointers are not just unsigned integers, even if that is what your compiler implements them with. They are an abstraction. Their behaviour is determined not by their implementation, but rather what the standard permits you do with them. When you act in ways the standard does not permit, the behaviour you get is undefined by the standard. Compilers can, and have been known to, exploit that fact to assume undefined behaviour cannot and does not occur. The program could behave unexpectedly on lines of code prior to the undefined behaviour as the compiler reorders and optimizes based on the assumption your code has well defined behaviour.
Pointers in c++ (and c) are just addresses to the memory (32/64bit numbers). There is no problem with increasing them or decreasing any way you want and you are not violating the memory or any other rule. You would be however violating the memory if you tried to read or write to the address pointed to by A after going through the for cycle.
As for what it is pointing to, most likely it's just some more space allocated to you by the new (and malloc under it) because it tends to give more space than you ask for, though this behaviour is not guaranteed. It might also point to heap data or just unassigned memory.

Local Variables Being Passed ( C++)

I have encountered a problem in my learning of C++, where a local variable in a function is being passed to the local variable with the same name in another function, both of these functions run in main().
When this is run,
#include <iostream>
using namespace std;
void next();
void again();
int main()
{
int a = 2;
cout << a << endl;
next();
again();
return 0;
}
void next()
{
int a = 5;
cout << a << endl;
}
void again()
{
int a;
cout << a << endl;
}
it outputs:
2
5
5
I expected that again() would say null or 0 since 'a' is declared again there, and yet it seems to use the value that 'a' was assigned in next().
Why does next() pass the value of local variable 'a' to again() if 'a' is declared another time in again()?
http://en.cppreference.com/w/cpp/language/ub
You're correct, an uninitialized variable is a no-no. However, you are allowed to declare a variable and not initialize it until later. Memory is set aside to hold the integer, but what value happens to be in that memory until you do so can be anything at all. Some compilers will auto-initialize variables to junk values (to help you catch bugs), some will auto-initialize to default values, and some do nothing at all. C++ itself promises nothing, hence it's undefined behavior. In your case, with your simple program, it's easy enough to imagine how the compiler created assembly code that reused that exact same piece of memory without altering it. However, that's blind luck, and even in your simple program isn't guaranteed to happen. These types of bugs can actually be fairly insidious, so make it a rule: Be vigilant about uninitialized variables.
An uninitialized non-static local variable of *built-in type (phew! that was a mouthful) has an indeterminate value. Except for the char types, using that value yields formally Undefined Behavior, a.k.a. UB. Anything can happen, including the behavior that you see.
Apparently with your compiler and options, the stack area that was used for a in the call of next, was not used for something else until the call of again, where it was reused for the a in again, now with the same value as before.
But you cannot rely on that. With UB anything, or nothing, can happen.
* Or more generally of POD type, Plain Old Data. The standard's specification of this is somewhat complicated. In C++11 it starts with §8.5/11, “If no initializer is specified for an object, the object is default-initialized; if no initialization is performed, an object with automatic or dynamic storage duration has indeterminate value.”. Where “automatic … storage duration” includes the case of local non-static variable. And where the “no initialization” can occur in two ways via §8.5/6 that defines default initialization, namely either via a do-nothing default constructor, or via the object not being of class or array type.
This is completely coincidental and undefined behavior.
What's happened is that you have two functions called immediately after one another. Both will have more or less identical function prologs and both reserve a variable of exactly the same size on the stack.
Since there are no other variables in play and the stack is not modified between the calls, you just happen to end up with the local variable in the second function "landing" in the same place as the previous function's local variable.
Clearly, this is not good to rely upon. In fact, it's a perfect example of why you should always initialize variables!

Throwing an array local to a try block

From C++ Primer 18.1.1:
If the [thrown] expression has an array or function type, the expression is
converted to its corresponding pointer type.
How is it that this program can produce correct output of 9876543210 (g++ 5.2.0)?
#include <iostream>
using namespace std;
int main(){
try{
int a[10] = {9,8,7,6,5,4,3,2,1,0};
throw a;
}
catch(int* b) { for(int i = 0; i < 10; ++i) cout << *(b+i); }
}
From the quote, throw a would create an exception object of type int* which is a pointer to the first element of the array. But surely the array elements of a would be destroyed when we exit the try block and enter the catch clause since we change block scope? Am I getting a false positive or are the array elements "left alone" (not deleted) during the duration of the catch clause?
Dereferencing a dangling pointer is Undefined Behaviour.
When a program encounters Undefined Behaviour, it is free to do anything. Which includes crashing and making daemons fly out of your nose, but it also includes doing whatever you expected.
In this case, there are no intervening operations that would overwrite that part of memory and access past the stack pointer (below it, because stack grows down on most platforms) is normally not checked.
So yes, this is a false positive. The memory is not guaranteed to contain the values any more and is not guaranteed to be accessible at all, but it still happens to contain them and be accessible.
Also note, that gcc optimizations are rather infamous for relying on the program not invoking undefined behaviour. Quite often if you have an undefined behaviour, the unoptimized version appears to work, but once you turn on optimizations, it starts doing something completely unexpected.
But surely the array elements of a would be destroyed when we exit the try block and enter the catch clause since we change block scope?
Correct.
Am I getting a false positive or are the array elements "left alone" (not deleted) during the duration of the catch clause?
They're not "left alone". The array is destroyed as you correctly assumed. The program is accessing invalid memory. The behaviour is undefined.
How is it that this program can produce correct output of 9876543210 (g++ 5.2.0)?
There is no correct output when the behaviour is undefined. The program can produce what it did because it can produce any output when the behaviour is undefined.
Reasoning about UB is usually pointless, but in this case, the contents of the invalid memory could be identical if the part of the memory had not yet been overwritten by the program.
You will find later in this chapter a Warning:
Throwing a pointer requires that the object to which the pointer
points exist wherever the corresponding handler resides.
so your example would be valid if a array were static or global, otherwise its UB. Or (as Jan Hudec writes in comment) in the enclosing block of the try/catch statement.

Uninitialized variable behaviour in C++

I've checked myself, I wrote a program like this
int main() {
int i;
cout << i;
return 0;
}
I ran the program a few times and the result was same all the time, zero.
I've tried it in C and the result was the same.
But my textbook says
If you don’t initialize an variable that’s defined
inside a function, the variable value remain undefined.That means the element takes on
whatever value previously resided at that location in memory.
How's this possible when the program always assign a free memory location to a variable? How could it be something other than zero(I assume that default free memory value is zero)?
How's this possible when the program always assign a free memory
location to a variable? How could it be something rather than zero?
Let's take a look at an example practical implementation.
Let's say it utilizes stack to keep local variables.
void
foo(void)
{
int foo_var = 42;
}
void
bar(void)
{
int bar_var;
printf("%d\n", bar_var);
}
int
main(void)
{
bar();
foo();
bar();
}
Totally broken code above illustrates the point. After we call foo, certain location on the stack where foo_var was placed is set to 42. When we call bar, bar_var occupies that exact location. And indeed, executing the code results in printing 0 and 42, showing that bar_var value cannot be relied upon unless initialized.
Now it should be clear that local variable initialisation is required. But could main be an exception? Is there anything which could play with the stack and in result give us a non-zero value?
Yes. main is not the first function executed in your program. In fact there is tons of work required to set everything up. Any of this work could have used the stack and leave some non-zeros on it. Not only you can't expect the same value on different operating systems, it may very well suddenly change on the very system you are using right now. Interested parties can google for "dynamic linker".
Finally, the C language standard does not even have the term stack. Having a "place" for local variables is left to the compiler. It could even get random crap from whatever happened to be in a given register. It really can be totally anything. In fact, if an undefined behaviour is triggered, the compiler has the freedom to do whatever it feels like.
If you don’t initialize an variable that’s defined inside a function, the variable value remain undefined.
This bit is true.
That means the element takes on whatever value previously resided at that location in memory.
This bit is not.
Sometimes in practice this will occur, and you should realise that getting zero or not getting zero perfectly fits this theory, for any given run of your program.
In theory your compiler could actually assign a random initial value to that integer if it wanted, so trying to rationalise about this is entirely pointless. But let's continue as if we assumed that "the element takes on whatever value previously resided at that location in memory"…
How could it be something rather than zero(I assume that default free memory value is zero)?
Well, this is what happens when you assume. :)
This code invokes Undefined Behavior (UB), since the variable is used uninitialized.
The compiler should emit a warning, when a warning flag is used, like -Wall for example:
warning: 'i' is used uninitialized in this function [-Wuninitialized]
cout << i;
^
It just happens, that at this run, on your system, it had the value of 0. That means that the garbage value the variable was assigned to, happened to be 0, because the memory leftovers there suggested so.
However, notice that, kernel zeroes appear relatively often. That means that it is quite common that I can get zero as an output of my system, but it is not guaranteed and should not be taken into a promise.
Static variables and global variables are initialized to zero:
Global:
int a; //a is initialized as 0
void myfunc(){
static int x; // x is also initialized as 0
printf("%d", x);}
Where as non-static variables or auto variables i.e. the local variables are indeterminate (indeterminate usually means it can do anything. It can be zero, it can be the value that was in there, it can crash the program). Reading them prior to assigning a value results in undefined behavior.
void myfunc2(){
int x; // value of x is assigned by compiler it can even be 0
printf("%d", x);}
It mostly depends on compiler but in general most cases the value is pre assumed as 0 by the compliers