I am learning now C, and these days I am studying pointers and I just come with a question!
int *ptr; //declare the ptr
ptr = &var; //init the ptr with the address of the variable var
with these lines, I created a pointer and I linked the ptr with a variable. My question is this, when I declare a pointer int *ptr; and I don't initialize it with an address, this pointer where it points?
In C, variables are generally not initialized unless you specifically say so:
int a; // not initialized
int b = 1; // initialized
int arr[10]; // not initialized
int brr[4] = { 1 }; // initialized as { 1, 0, 0, 0 }
void * p; // not initialized
void * q = &a; // initialized
(There are exceptions for variables with static or thread-local storage, which are always zero-initialized.)
It is not allowed to try and get at the value of an uninitialized variable. The only thing you can do with an uninitialized variable is assign to it, which does not access its current value, but only assigns a new value to it. Before initialization or assignment, the current value of a variable is "indeterminate" and you must not attempt to access it. Doing so results in undefined behaviour.
This is true for all variables, but in particular it applies to your pointer variable. It simply has no meaningful value until you assign one.
void * p; // not initialized
if (p) { /*...*/ } // undefined behaviour!
printf("%p\n", p); // undefined behaviour!
p = &a; // now p has a well-defined value
The technical term for the action that is causing undefined behaviour is the so-called "lvalue conversion". That is the moment in which you take a named variable (an "lvalue") and use its content. E.g. C11, 6.3.2.1/2 says:
If the lvalue designates an object of automatic storage duration [...] and that object
is uninitialized (not declared with an initializer and no assignment to it has been
performed prior to use), the behavior is undefined.
It is just like any other uninitialized local variable -- it is undefined where it points or what value it contains, and you are not allowed to use it (e.g., dereference it) until it is initialized. As stated in #WhozCraig's comment, almost all other operations are forbidden as well (using the pointer's value at all, including arithmetic and comparisons). Uninitialized non-pointer variables (even those with simple types such as ints) cannot be used for any operations that access their values, either.
Actually, as it has been stated in almost all answers so far, the pointer's value is unknown and consists of the contents of the memory at that location when it was allocated.
Contrary to what some answers state though, noone and nothing is going to forbid you dereferencing it, or doing any kind of operation with this pointer.
As a result, using such a pointer will produce any kind of unpredictable results. It is not only best practice but a requirement for producing less buggy code, to initialize a pointer on declaration to something, even if that something is, simply, NULL.
It points to a random memory location. Dereferencing such a pointer usually leads to a segfault.
In this case, it will point anywhere. You don't know. The contents of the pointer will be whatever was at the memory location before. So this is very dangerous and should be avoided. You should always init a pointer with NULL, then it will point to "nothing" in a defined way.
Like any other non-static variable in C, it's not initialized automatically. It contains whatever junk data was in the memory slot, and so deferencing it before assigning a proper value to it is likely to be a bad idea.
Related
Background info: My program involves creating a hash table and one of my functions is free_hash(struct hash_table *table).
struct hash_table *table points to an array of struct hash_entry pointers. To test my free_hash function in main I have a void *test_free = what. the declaration and initialization for what is hash_table *what = new_hash(array_size).
this is struct hash_table *new_hash() it returns a function that returns a pointer to a new initialized struct hash_table.
My question: After freeing what, eg.free_hash(what), what happens to test_free. What is the address of it/the value of what it is pointing at. And is there any other way I can make sure that what has been destructed/freed.
test_free and what are pointers. The value they have is basically an address. And you assigned the same address to both of them. Nothing happens to either variable once you free that to which they point.
Once you do, the pointers are deemed to be indeterminate, so it becomes undefined behaviour to deference either one. But there's nothing in either variable that indicates this. The onus is on the programmer to ensure no attempts is made to access a freed structure.
As for checking if everything was properly freed, there's -fsanitize=address, valgrind, etc.
C 2018 6.2.4 2 says “… The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime.” When you release memory with free, the lifetime of any objects in it end, so any pointers to this memory become indeterminate. “Indeterminate” means the pointer value is not even fixed; it may act as if it has a different value each time it is used.
This rule exists because there have been C implementations in which maintaining pointers required auxiliary information associated with the allocated memory. So the “value” of a pointer was not represented just by the bits directly in the memory used for the pointer object itself. Once the memory, and its auxiliary information, are released, it might no longer be possible to interpret the value of the pointer correctly.
In most modern C implementations, addresses are implemented simply as numbers in a “flat” address space. In this case, no auxiliary information is needed to interpret the value of a pointer or to work with it as by adding offsets to it. However, because the rule exists, optimizers in compilers may treat any pointer to freed memory as indeterminate.
For example, in this code:
void *x;
free(p);
if (SomeTest)
x = p;
else
x = q;
printf("%p\n", x);
the compiler is allowed to optimize this to:
void *x;
free(p);
x = q;
printf("%p\n", x);
even if SomeTest is true. That is the fact that p is indeterminate after free means it is allowed to have any value, so it could have the value of q, so the if statement would just be:
if (SomeTest)
x = q;
else
x = q;
which of course can be optimized to x = q;.
In short, once you release memory, the C standard does not give you any assurance your program will behave as if a pointer to that memory has any particular value. It may act as if the pointer has a different value each time the program uses it.
Can anybody tell me, the meaning of wild pointer in C, how to obtain it and is this available in C++?
The standard does not define or use the term "wild". I'd be careful "correcting" other people's opinions about what it means, and I'd especially avoid quoting random non-normative internet junk to support my position.
To me, it would mean a pointer that neither refers to a legitimate object, nor is NULL. Possible sources of these types of pointer values might include uninitialized pointer objects, objects that have ceased to exist, computed pointer values, improperly aligned pointer values, accidental corruption of the pointer itself, or what it pointed to, etc.
int main(void)
{
int *p; // uninitialized and non-static; value undefined
{
int i1;
p = &i1; // valid
} // i1 no longer exists; p now invalid
p = (int*)0xABCDEF01; // very likely not the address of a real object
{
int i2;
p = (int*)(((char*)&i2) + 1); // p very likely to not be aligned for int access
}
{
char *oops = (char*)&p;
oops[0] = 'f'; oops[1] = 35; // p was clobbered
}
}
and so on, and so forth. There are all kinds of ways to get an invalid pointer value in C. My favourite has got to be the guy who tried to "save" his objects by writing their addresses to a file. Strangely, when he read back those pointer values during a different run of the program, they didn't point to his objects any more. Fancy, that.
But that's just what wild means to me. Since it's not a normative term, it means whatever the person who spoke or wrote it meant it to mean. Ask him or her.
A wild pointer in C is a pointer that has not been initialised prior to its first use.
From Wikipedia:
Wild pointers are created by omitting
necessary initialization prior to
first use. Thus, strictly speaking,
every pointer in programming languages
which do not enforce initialization
begins as a wild pointer.
This most often occurs due to jumping
over the initialization, not by
omitting it. Most compilers are able
to warn about this.
eg
int f(int i)
{
char* dp; //dp is a wild pointer
...
}
It is not s standard term. It is normally used to refer to the pointers pointing to invalid memory location.
int *p;
*p = 0; //P is a wild pointer
Or
int *p = NULL;
{
int a;
p = &a; // as soon as 'a' goes out of scope,'p' is pointing to invalid location
}
*p = 0;
To get a wild (aka dangling) pointer you:
Create an object
Create a pointer to that object
Delete the object
Forget to set the pointer to null
The pointer is now classed as "wild" as it's pointing to an arbitrary piece of memory and using it in this state could cause problems with your program.
A pointer which is not initialized with any address is called as a wild pointer. It may contain any garbage address, so dereferencing a wild pointer is dangerous
A wild pointer is any pointer that is used (particularly as an L_value {ie (*pointer) = x } ) while having a value that is either not correct or no longer correct. It could also be used to describe the using of memory that is not defined as a pointer as a pointer (possibly by having followed a wild pointer or by using outdated structure definitions).
There's no official definition. It's just words that we use when referring to certain pointer errors or the results of those errors.
Wiki
It's a pointer to either uninitialized object or an object with a bad state. using this pointer will cause trouble. the wiki is a good source of explanation.
Wild pointer is a pointer that doesn’t point to either a valid object (of the indicated type, if applicable), or to a distinguished null value, if applicable.
Read more about Wild Pointer here
Wild pointer is a pointer which declaration is present but it has not been defined yet.Means we have declare a pointer -
data_type *ptr; //but not define which address it is containing
*ptr=100//wild pointer does not point to any valid address.so we will get ERROR
printf("ptr:%d",ptr);//we will get:0(in gcc compiler)
a ponter which not have locating any data type varable that varable is call the wild pointer
Uninitialized pointer is called Wild Pointer.
Suppose if you try
int *p; //pointing to any random or unknown location.
*p= 16; /Some unknown memory location is being corrupted.This should never be done./
This can create a great threat to your program. B'Coz because they point to some arbitrary memory location and changing the content of that location may cause a program to crash or behave badly.
I've read the followed post:
Is returning a heap-allocated pointer from function OK?
Which shows that a pointer pointing to a heap allocated variable is returned is alright. However, is the pointer technically a "stack allocated variable", which would then get deallocated upon returning of the function?
For example:
int* test(){
int arr[5];
int *ptr = arr;
return ptr; //deallocated ptr?
}
int *test2(){
int arr[5];
return arr;
}
In test
Also, is it right to say arr is a pointer that points to some newly created int array arr, pointing at &arr[0]. If arr is not a pointer, why is it valid to return it satisfying the function return type?
Since both ptr and arr are supposedly stack allocated, why does the code only work in test() and not test2()? Does test() give an undefined behavior?
They will both be undefined behaviour, if the returned value is accessed. So, none of them are "OK".
You're trying to return a pointer to a block-scoped variable which is of auto storage duration. So, once the scope ends, the lifetime of the variable comes to an end.
Quoting C11, chapter §6.2.4/P2, regarding the lifetime (emphasis mine)
The lifetime of an object is the portion of program execution during which storage is
guaranteed to be reserved for it. An object exists, has a constant address, and retains
its last-stored value throughout its lifetime. If an object is referred to outside of its
lifetime, the behavior is undefined [...]
Then, from P5,
An object whose identifier is declared with no linkage and without the storage-class
specifier static has automatic storage duration, [...]
and
For such an object that does not have a variable length array type, its lifetime extends
from entry into the block with which it is associated until execution of that block ends in
any way. [...]
So, in your case, the variable arr is having automatic storage and it's lifetime is limited to the function body. Once the address is returned to caller, attempt to access the memory at that address would be UB.
Oh, and there's no "stack" or "heap" in C standard, All we have is the lifetime of a variable.
Both test and test2() are equivalent. They return an implementation-defined pointer that you must not dereference, or else UB ensues.
If you don't dereference the returned pointer, calling test() or test2() does not result in undefined behavior, but such a function is probably not very useful.
Upon entering a function a new stack frame is added to the stack. The stack frame is where all autos (non static variables declared in the function) are stored. When we leave the function the return value is placed in a register (generally R0) in the CPU and the stack pointer is then decreased to remove the stack frame. We then return control to the point where we called the function and we get the return value from the register.
So in this case you have int arr[5], as the program enters the function a new stack frame is added to the stack. In this stack frame there is memory for 5 integers in an array, the variable arr is indeed now equivalent a pointer to the first element in the array. When you return the variable arr you are returning a pointer to the data in the stack frame, when the function exits and you return back to the previous function the stack pointer is then decreased to remove the stack frame of the function you just exited.
The pointer is still pointing to that place in memory where we previously had an array allocated. So when the stack is increased the memory arr is pointing to will be over written. Changing the data the returned value points to could result in some very "exciting" stuff happening as we don't know when the memory is now used for.
Array vs pointer example:
char arr[5];
char * ptr = arr;
In this case the compiler knows the size of arr and does not know the size of ptr so we can do sizeof(arr) and the compiler will do the calculation at compile time. When it comes to run time, they are equivalent values in memory.
Both cases are technically the same.
In both cases, a pointer to arr is returned. While the value of the returned pointer indeed points to the memory that used to contain arr, arr is already freed from the memory.
Therefore, sometime when you access the pointer you would still find there the contents of arr, which were just happened to not overridden yet. Other times, you might access it after this memory has been overridden, and get undefined data or even segmentation fault.
You still seem residually confused by the pointer being an automatic variable as well, so that you are afraid that returning it would be invalid even if it pointed to some valid memory (say, a static array).
It is important to remember that in C all parameter and return value passing is done by value. If you "return a pointer" as in return p; it is exactly the same mechanism as if you "returned an integer", as in return i;: The value of the variable is copied somewhere and obtained by the caller. In the case of i that value may be 42; in the case of p the value may be 3735928559 (or in other words, 0xdeadbeef). That value denotes the place in memory where e.g. your array was residing before it ceased to exist because the function returned. The address does not change when you copy it any more than 42 changes, and is completely independent of the lifetime of the variable p which once contained it — it was, after all, copied out of it just in time.1
1This is beyond the scope of the question but technically conceptually, a temporary object is created for the return value. The lifetime and semantics of temporaries are more systematically categorized in modern C++.
I have the following code and I am confused why is it now working:
#include<stdio.h>
void modif(const int *p)
{
*(p+1)=5;
}
int main()
{
int a=1;
printf("\n%d",a);
modif(&a);
printf("\n%d",a);
return 0;
}
The error I am getting is this one:
main.c: In function 'modif':
main.c:6:9: error: assignment of read-only location '*(p + 4)'
*(p+1)=5;
^
exit status 1
In my opinion the address next to p should be modifiable. I have tried to modify the values at addresses that were further away and the result was the same.
When using "const" keyword before a parameter passed by reference what is the first address that is actually modifiable?
This statement
*(p+1)=5;
is problematic for a couple of reasons.
p is const-qualified. So that's the reason for the error you get.
You violate the promise you made to the compiler (that you wouldn't modify the object pointed to by p).
If you didn't have the const qualifier, it's still wrong.
Because the object that p points to is a single int, so dereferencing p+1 is undefined behaviour.
Note that evaluating p+1 is fine even if p points to a single int object. It's allowed per C11, 6.5.6/9.
But dereferencing it is not valid.
If there's a valid object at p + 1 (provided that object itself is mutable - otherwise, this will be undefined behaviour), you could cast away the const in modif() and legally modify it. For example, the below is valid (but not something I recommend - if you want modif to be able to modify a's contents, it doesn't make sense to qualify p with const here).
#include<stdio.h>
void modif(const int *p)
{
int *q = (int*)p;
*(q+1)=5;
}
int main()
{
int a[2] = {0};
modif(a);
printf("\n%d, %d",a[0], a[1]);
return 0;
}
'In my opinion the address next to p should be modifiable'
Authors of C language have opposite opinion. And it's their opinion which counts.
The C semantics allows you to perform a so-called pointer arithmetics, which includes adding and subtracting integers to/from typed pointers. The pointer value resulting from such operation points to an element of the same array, respective number of items farther or earlier in the array.
However the const modifier applies to the whole array (despite its size being not specified), so it does not vanish in such operation. If it did, you could just do *((p+1)-1) to access a *p variable without the const restriction!
You're just passing a pointer which in C may point to an arbitrarily sized array of objects -- size 1 for a single object is just one possible case. It's your job as a programmer to find means how the function knows how many objects there are.
If the pointer is a pointer to a const, this means the whole array is immutable.
In your code, your pointer only points to a single object, so accessing the non-existing object at index 1 is just undefined behavior. If this object would exist, would you expect it to be modifyable through a const pointer? Of course not ...
Can anybody tell me, the meaning of wild pointer in C, how to obtain it and is this available in C++?
The standard does not define or use the term "wild". I'd be careful "correcting" other people's opinions about what it means, and I'd especially avoid quoting random non-normative internet junk to support my position.
To me, it would mean a pointer that neither refers to a legitimate object, nor is NULL. Possible sources of these types of pointer values might include uninitialized pointer objects, objects that have ceased to exist, computed pointer values, improperly aligned pointer values, accidental corruption of the pointer itself, or what it pointed to, etc.
int main(void)
{
int *p; // uninitialized and non-static; value undefined
{
int i1;
p = &i1; // valid
} // i1 no longer exists; p now invalid
p = (int*)0xABCDEF01; // very likely not the address of a real object
{
int i2;
p = (int*)(((char*)&i2) + 1); // p very likely to not be aligned for int access
}
{
char *oops = (char*)&p;
oops[0] = 'f'; oops[1] = 35; // p was clobbered
}
}
and so on, and so forth. There are all kinds of ways to get an invalid pointer value in C. My favourite has got to be the guy who tried to "save" his objects by writing their addresses to a file. Strangely, when he read back those pointer values during a different run of the program, they didn't point to his objects any more. Fancy, that.
But that's just what wild means to me. Since it's not a normative term, it means whatever the person who spoke or wrote it meant it to mean. Ask him or her.
A wild pointer in C is a pointer that has not been initialised prior to its first use.
From Wikipedia:
Wild pointers are created by omitting
necessary initialization prior to
first use. Thus, strictly speaking,
every pointer in programming languages
which do not enforce initialization
begins as a wild pointer.
This most often occurs due to jumping
over the initialization, not by
omitting it. Most compilers are able
to warn about this.
eg
int f(int i)
{
char* dp; //dp is a wild pointer
...
}
It is not s standard term. It is normally used to refer to the pointers pointing to invalid memory location.
int *p;
*p = 0; //P is a wild pointer
Or
int *p = NULL;
{
int a;
p = &a; // as soon as 'a' goes out of scope,'p' is pointing to invalid location
}
*p = 0;
To get a wild (aka dangling) pointer you:
Create an object
Create a pointer to that object
Delete the object
Forget to set the pointer to null
The pointer is now classed as "wild" as it's pointing to an arbitrary piece of memory and using it in this state could cause problems with your program.
A pointer which is not initialized with any address is called as a wild pointer. It may contain any garbage address, so dereferencing a wild pointer is dangerous
A wild pointer is any pointer that is used (particularly as an L_value {ie (*pointer) = x } ) while having a value that is either not correct or no longer correct. It could also be used to describe the using of memory that is not defined as a pointer as a pointer (possibly by having followed a wild pointer or by using outdated structure definitions).
There's no official definition. It's just words that we use when referring to certain pointer errors or the results of those errors.
Wiki
It's a pointer to either uninitialized object or an object with a bad state. using this pointer will cause trouble. the wiki is a good source of explanation.
Wild pointer is a pointer that doesn’t point to either a valid object (of the indicated type, if applicable), or to a distinguished null value, if applicable.
Read more about Wild Pointer here
Wild pointer is a pointer which declaration is present but it has not been defined yet.Means we have declare a pointer -
data_type *ptr; //but not define which address it is containing
*ptr=100//wild pointer does not point to any valid address.so we will get ERROR
printf("ptr:%d",ptr);//we will get:0(in gcc compiler)
a ponter which not have locating any data type varable that varable is call the wild pointer
Uninitialized pointer is called Wild Pointer.
Suppose if you try
int *p; //pointing to any random or unknown location.
*p= 16; /Some unknown memory location is being corrupted.This should never be done./
This can create a great threat to your program. B'Coz because they point to some arbitrary memory location and changing the content of that location may cause a program to crash or behave badly.