How to make uninitiated pointer not equal to 0/null? - c++

I am a c++ learner. Others told me "uninitiatied pointer may point to anywhere". How to prove that by code.?I made a little test code but my uninitiatied pointer always point to 0. In which case it does not point to 0? Thanks
#include <iostream>
using namespace std;
int main() {
int* p;
printf("%d\n", p);
char* p1;
printf("%d\n", p1);
return 0;
}

Any uninitialized variable by definition has an indeterminate value until a value is supplied, and even accessing it is undefined. Because this is the grey-area of undefined behaviour, there's no way you can guarantee that an uninitialized pointer will be anything other than 0.
Anything you write to demonstrate this would be dictated by the compiler and system you are running on.
If you really want to, you can try writing a function that fills up a local array with garbage values, and create another function that defines an uninitialized pointer and prints it. Run the second function after the first in your main() and you might see it.
Edit: For you curiosity, I exhibited the behavior with VS2015 on my system with this code:
void f1()
{
// junk
char arr[24];
for (char& c : arr) c = 1;
}
void f2()
{
// uninitialized
int* ptr[4];
std::cout << (std::uintptr_t)ptr[1] << std::endl;
}
int main()
{
f1();
f2();
return 0;
}
Which prints 16843009 (0x01010101). But again, this is all undefined behaviour.

Well, I think it is not worth to prove this question, because a good coding style should be used and this say's: Initialise all variables! One example: If you "free" a pointer, just give them a value like in this example:
char *p=NULL; // yes, this is not needed but do it! later you may change your program an add code beneath this line...
p=(char *)malloc(512);
...
free(p);
p=NULL;
That is a safe and good style. Also if you use free(p) again by accident, it will not crash your program ! In this example - if you don't set NULL to p after doing a free(), your can use the pointer by mistake again and your program would try to address already freed memory - this will crash your program or (more bad) may end in strange results.
So don't waste time on you question about a case where pointers do not point to NULL. Just set values to your variables (pointers) ! :-)

It depends on the compiler. Your code executed on an old MSVC2008 displays in release mode (plain random):
1955116784
1955116784
and in debug mode (after croaking for using unitialized pointer usage):
-858993460
-858993460
because that implementation sets uninitialized pointers to 0xcccccccc in debug mode to detect their usage.
The standard says that using an uninitialized pointer leads to undefined behaviour. That means that from the standard anything can happen. But a particular implementation is free to do whatever it wants:
yours happen to set the pointers to 0 (but you should not rely on it unless it is documented in the implementation documentation)
MSVC in debug mode sets the pointer to 0xcccccccc in debug mode but AFAIK does not document it (*), so we still cannot rely on it
(*) at least I could not find any reference...

Related

Why Simply de-referencing a pointer with NULL assigned is not crashing [duplicate]

This question already has answers here:
What happens in OS when we dereference a NULL pointer in C?
(5 answers)
Closed 6 years ago.
#include <iostream>
int main()
{
int *ptr = NULL;
// It does not crash
*ptr; --------> Point-1
//But this statment crashed
std::cout<<"Null:"<<*ptr<<"\n"; ------> Point-2
return 0;
}
In the above code when i comment "Point-2" the code is not crashed.
But when i un-comment the "Point-2" it is crashed.
Since ptr is NULL ideally the Point-1 should also crash. Please corret me if i am wrong.
Can someone explain me why the code not crashed when i simply dereffernece the pointer ?
Dereferencing a null pointer is undefined behavior. Undefined behavior is not equal to error. Anything may happen if you triggered undefined behavior. If you are asking the other way:
Why is undefined behavior not causing an error instead of giving us strange behavior?
It may be due to many reason. One reason is performance. For example, in the implementation of std::vector (at least in MSVC), there is no check if the index is out of range in Release Mode. You can try to do this:
std::vector<int> v(4);
v[4]=0;
It will compile and run. You may got strange behavior or you may not. However, in Debug mode it will throw exception at run-time. MSVC does the check in Debug Mode because performance is not important in Debug Mode. But it does not in Release Mode because performance matters.
The same applies for dereferencing a null pointer. You can image that the code of dereferencing will be put in a wrapper like this:
//Imaginary code
T& dereference(T* ptr){
if(ptr==nullptr){
throw;
}
return *ptr;
}
This part: if(ptr==nullptr){throw;} will slow the dereferencing process of every pointer in the context which is not desirable.
However, it may be done like this:
//Imaginary code
T& dereference(T* ptr){
#ifdef DEBUG
if(ptr==nullptr){
throw;
}
#endif
return *ptr;
}
I think you got the idea now.
In point 2 you try to display contents of 0x0 address, which generates access violation error.
In point 1, you do nothing with it, so the program doesn't have to access memory described by this pointer. This generates no acces violation error.

Conflicting outputs when value referenced by a pointer no longer exists

#include<iostream.h>
#include<conio.h>
int *p;
void Set()
{
int i;
i=7;
p=&i;
}
int Use()
{
double d;
d=3.0;
d+=*p;
//if i replace the above 3 statements with --> double d=3.0+*p; then output is 10 otherwise the output is some random value(address of random memory location)
//why is this happening? Isn't it the same?
return d;
}
void main()
{
clrscr();
Set();
cout<<Use();
getch();
}
My question is as mentioned in comments above.I want to know the exact reason for the difference in outputs.In the above code output is some address of random memory location and i understand that is because of i is a local variable of Set() but then how is it visible in the second case that is by replacing it with double d=3.0+*p; because then the output comes 10( 7+3 ) although 7 should not have been visible?
The result of using pointer p is undefined, it could also give you a segfault or just return 42. The technical reason behind the results your'e getting are probably:
i inside Set is placed on the stack. The value 7 ist stored there and p points to that location in memory. When you return from Set value remains in memory: the stack is not "destroyed", it's just the stack pointer which is reset. p still points to this location which still contains the integer representation of "3".
Inside Use the same location on the stack is reused for d.
When the compiler is not optimizing, in the first case (i.e. the whole computation in one line), it first uses the value 7 (which is still there in memory with p pointing to it), does the computation, overwrites the value (since you assign it to d which is at the same location) and returns it.
In the second case, it first overwrites the value withe the double value 3.0 and then takes the first 4 bytes interpreted as integer value for evaluating *p in d+=*p.
This case shows why returning pointers/references to local variables is such a bad thing: when writing the function Set you could even write some kind of unit tests and they would not detect the error. It might get unnoticed just until the software goes into production and has to perform some really critical task and just fails then.
This applies to all kindes of "undefined behaviour", especially in "low level" languages like C/C++. The bad thing is that "undefined" may very well mean "perfectly working until it's too late"...
After exiting function Set the value of pointer p becomes invalid due to destroying local variable i. The program has undefined behavior.

Unexpected output

#include <iostream>
int main()
{
const int i=10;
int *p =(int *) &i;
*p = 5;
cout<<&i<<" "<<p<<"\n";
cout<<i<<" "<<*p;
return 0;
}
Output:
0x22ff44 0x22ff44
10 5
Please Explain.
Well, your code obviously contains undefined behaviour, so anything can happen.
In this case, I believe what happens is this:
In C++, const ints are considered to be compile-time constants. In your example, the compiler basically replaces your "i" with number 10.
You've attempted to modify a const object, so the behavior is
undefined. The compiler has the right to suppose that the const
object's value doesn't change, which probably explains the
symptoms you see. The compiler also has the right to put the
const object in read only memory. It generally won't do so for
a variable with auto lifetime, but a lot will if the const has
static lifetime; in that case, the program will crash (on most
systems).
I'll take a shot at it: since there's no logical reason for that output, the compiler must have optimised that wretched cout<<i<<" " to a simple "cout<<"10 ". But it's just a hunch.

What happens to class members when malloc is used instead of new?

I'm studying for a final exam and I stumbled upon a curious question that was part of the exam our teacher gave last year to some poor souls. The question goes something like this:
Is the following program correct, or not? If it is, write down what the program outputs. If it's not, write down why.
The program:
#include<iostream.h>
class cls
{ int x;
public: cls() { x=23; }
int get_x(){ return x; } };
int main()
{ cls *p1, *p2;
p1=new cls;
p2=(cls*)malloc(sizeof(cls));
int x=p1->get_x()+p2->get_x();
cout<<x;
return 0;
}
My first instinct was to answer with "the program is not correct, as new should be used instead of malloc". However, after compiling the program and seeing it output 23 I realize that that answer might not be correct.
The problem is that I was expecting p2->get_x() to return some arbitrary number (whatever happened to be in that spot of the memory when malloc was called). However, it returned 0. I'm not sure whether this is a coincidence or if class members are initialized with 0 when it is malloc-ed.
Is this behavior (p2->x being 0 after malloc) the default? Should I have expected this?
What would your answer to my teacher's question be? (besides forgetting to #include <stdlib.h> for malloc :P)
Is this behavior (p2->x being 0 after malloc) the default? Should I have expected this?
No, p2->x can be anything after the call to malloc. It just happens to be 0 in your test environment.
What would your answer to my teacher's question be? (besides forgetting to #include for malloc :P)
What everyone has told you, new combines the call to get memory from the freestore with a call to the object's constructor. Malloc only does half of that.
Fixing it: While the sample program is wrong. It isn't always wrong to use "malloc" with classes. It is perfectly valid in a shared memory situation you just have to add an in-place call to new:
p2=(cls*)malloc(sizeof(cls));
new(p2) cls;
new calls the constructor, malloc will not. So your object will be in an unknown state.
The actual behaviour is unknown, because new acts pretty the same like malloc + constructor call.
In your code, the second part is missing, hence, it could work in one case, it could not, but you can't say exactly.
Why can't 0 be an arbitrary number too? Are you running in Debug mode? What compiler?
VC++ pre-fills newly allocated memory with a string of 0xCC byte values (in debug mode of-course) so you would not have obtained a zero for an answer if you were using it.
Malloc makes no guarantuee to zero out the memory it allocated and the result of the programm is undefined.
Otherwise there are many other things that keep this program from being correct C++. cout is in namespace std, malloc needs to included through#include <cstdlib> and iostream.h isn't standard compliant either.

Pointer to [-1]th index of array

How does a pointer points to [-1]th index of the array produce legal output everytime. What is actually happening in the pointer assignment?
#include<stdio.h>
int main()
{
int realarray[10];
int *array = &realarray[-1];
printf("%p\n", (void *)array);
return 0;
}
Code output:
manav#workstation:~/knr$ gcc -Wall -pedantic ptr.c
manav#workstation:~/knr$ ./a.out
0xbf841140
EDIT: If this scenario is valid, then can i use this to define an array whose index start from 1 instead of 0, namely: array[1], array[2],...
Youre simply getting a pointer that contains the address of that "imaginary" location, i.e. the location of the first element &realarray[0] minus the size of one element.
This is undefined behavior, and might break horribly if, for instance, your machine has a segmented memory architecture. It's working because the compiler writer has chosen to implement the arithmetic as outlined above; that could change at any moment, and another compiler might behave totally differently.
a[b] is defined as *(a+b)
therefore a[-1] is *(a-1)
Whether a-1 is a valid pointer and therefore the dereference is valid depends on the context the code is used in.
The behaviour is undefined.
What you have observed may have happened in your particular compiler and configuration, but anything may happen in a different situation. You cannot rely on this behaviour at all.
The behavior is undefined. You can only calculate a pointer to any of the elements of an array, or one past, but that's it. You can only dereference a pointer to any of the elements of an array (not the one past pointer). Looking at your variable names, looks like you're asking a question from this C FAQ. I think that the answer on the FAQ is very good.
Although, as others have noted, it is undefined behaviour in this case, it compiles without warnings because in general, foo[-1] might be valid.
For example, this is fine:
int realarray[10] = { 10, 20, 30, 40 };
int *array = &realarray[2];
printf("%d\n", array[-1]);
In C and C++, array indexes are not checked at runtime. You are performing pointer arithmetic which may or may not end up giving defined results (not here).
However, in C++ you can use an array class that does provide bounds checks, e.g boost::array or std::tr1::array (to be added to standard library in C++0x):
#include <cstdio>
#include <boost/array.hpp>
int main()
{
try {
boost::array<int, 10> realarray;
int* p = &realarray.at(-1);
printf("%p\n", (void *)p);
} catch (const std::exception& e) {
puts(e.what());
}
}
Output:
array<>: index out of range
Also produces a compiler warning:
8 test.cpp [Warning] passing negative
value -0x000000001' for converting 1
ofT& boost::array::at(size_t)
[with T = int, unsigned int N = 10u]'
It simply points to the address of the item just ahead of the array in memory.
The array can simply be thought of as being a pointer. This is then simply decremented by one.
Here you just performing the pointer arithmetic , It will get firs index address of the relarray
See, if you &relarray[+1] , you would get the second element address of the array. since
&relarray[0] is pointing the first index address.
array points to one location before the starting address of realarray. However, what confused me is why does this compiled without any warnings.
You're just pointing to the 4 bytes located before the array.
This is perfectly well defined. Your code is guaranteed to be accepted by all compilers, and never crash at run time. C/C++ pointers are a numeric data type that obey the rules of arithmetic. Addition and subtraction work, and the bracket notation [] is just a fancy syntax for addition. NULL is literally the integer 0.
And this is why C/C++ are dangerous. The compiler will let you create pointers that point anywhere without complaint. Dereferencing the wild pointer in your example, *array = 1234; would produce undefined behavior, anything from subtle corruption to a crash.
Yes, you could use it to index from 1. Don't do this! The C/C++ idiom is to always index from 0. Other people who saw the code indexing from 1 would be tempted to "fix" it to index from 0.
The experiment could have provided little more clue if it was the following. Instead of printing the pointer value as
printf("%p\n", (void *)array);
, print the array element value
printf("%d\n", *array);
Thats because printing a pointer with %p will always produce some output (without any misbehavior), but nothing can be deduced from it.