pointer to a structure - c

this will give a proper output even though i have not allocated memory and have declared a pointer to structure two inside main
struct one
{
char x;
int y;
};
struct two
{
char a;
struct one * ONE;
};
main()
{
struct two *TWO;
scanf("%d",&TWO->ONE->y);
printf("%d\n",TWO->ONE->y);
}
but when i declare a pointer to two after the structure outside main i will get segmentation fault but why is it i don't get segmentation fault in previous case
struct one
{
char x;
int y;
};
struct two
{
char a;
struct one * ONE;
}*TWO;
main()
{
scanf("%d",&TWO->ONE->y);
printf("%d\n",TWO->ONE->y);
}

In both the cases TWO is a pointer to a object of type struct two.
In case 1 the pointer is wild and can be pointing anywhere.
In case 2 the pointer is NULL as it is global.
But in both the cases it a pointer not pointing to a valid struct two object. Your code in scanf is treating this pointer as though it was referring to a valid object. This leads to undefined behavior.

Because what you are doing is undefined behaviour. Sometimes it seems to work. That doesn't mean you should do it :-)
The most likely explanation is to do with how the variables are initialised. Automatic variables (on the stack) will get whatever garbage happens to be on the stack when the stack pointer was decremented.
Variables outside functions (like in the second case) are always initialised to zero (null pointer for pointer types).
That's the basic difference between your two situations but, as I said, the first one is working purely by accident.

When declaring a global pointer, it will be initialized to zero, and so the generated addresses will be small numbers that may or may not be readable on your system.
When declaring an automatic pointer, its initial value is likely to be much more interesting. It will be, in this case, whatever the run-time library left at that point on the stack prior to calling main(), or perhaps a left-over value from the compiler-generated stack-frame setup code. It is somewhat likely to be a saved stack pointer or frame pointer, which is a valid pointer if used with small offsets.
So anyway, the uninitialized pointer does have something in it, and one value leads to a fault while the other, for now, on your system, does not.
And that's because the segmentation fault is a mechanism of the OS and not the C language.
A fault is a block-based mechanism that allocates to itself and other programs some number of pages -- which are each several K -- and it protects itself and other program's pages while allowing your program free reign. You must stray outside of the block context or try to write a read-only page (even if yours) to generate a fault. Simply breaking a language rule is not necessarily enough. The OS is happy to let your program misbehave and act oddly due to its wild references, just as long as it only reads and writes (or clobbers) itself.

Related

Why is Pointer = NULL defined as clean code?

So my programming teacher told us, that if you don't use a pointer but like to declare it, it is always better to initialize it with NULL. How does it prevent any errors if i don't even use it?
Or if I am wrong, what are the benefits of it?
De-referencing NULL is likely (guaranteed?) to cause a segmentation fault, immediately crashing your app and alerting you to the unsafe memory access you just preformed.
Leaving your pointer uninitialized will mean it still has whatever junk was left over from the previous user of that memory. It's entirely possible for that to be a pointer to a real memory region in your app. Dereferencing it will be undefined behavior, might cause a seg fault, or it might not. The latter is the worst case, which you should fear. Your app will just keep chugging along with whatever non-sense behavior resulted from that.
Here's a demonstration:
#include <stdio.h>
#include <stdlib.h>
void i_segfault() {
fflush(stdout); // Flush whatever is left of STDOUT before we blow up
int *i = NULL;
printf("%i", *i); // Boom
}
void use_some_memory() {
int *some_pointer = malloc(sizeof(int));
*some_pointer = 123;
printf(
"I used the address %p to store a pointer to %p, which contains %i\n",
&some_pointer, some_pointer, *some_pointer
);
}
void i_dont_segfault() {
int *my_new_pointer; // uninitialized
printf(
"I re-used the address %p, which still has a lingering value %p, which still points to %i\n",
&my_new_pointer, my_new_pointer, *my_new_pointer
);
}
int main(int argc, char *argv[]) {
use_some_memory();
i_dont_segfault();
i_segfault();
}
There are at least two ways to make sure your program does not use an uninitialized pointer:
You can design and write your program carefully so that you are sure that program control never flows through a path that uses the pointer without initializing it first.
You can initialize the pointer to NULL.
The first can be hard, depending on the program, and humans keep making mistakes with it. The second is easy.
On the other hand, the second only solves one problem: It ensures that if you use the pointer without otherwise initializing it, it will have an assigned value. Further, in many systems, it ensures that if you attempt to use that value to access a pointed-to object, your program will crash rather than do something worse, like corrupt data and produce wrong results or erase valuable information.
That is a useful problem to solve, because it means this bug of failing to assign the desired value is likely to be caught during testing and, even if it is not, the damage is may due is likely to be limited. However, this does not solve the problem of ensuring that the pointer is assigned the desired value before it is used. So, like many of these code recommendations, it is a useful tip to help limit human errors, but it is not a complete solution.
If you don't initialize a variable (by mistake) the problem is that your program can be even more anomalous than normal. Imagine you have declared an enum with the values ONE, TWO, THREE, and you forget to initialize it, and at some point you include the following code:
switch(my_var) {
case ONE: /* do one */
...
break;
case TWO: /* do two */
...
break;
case THREE: /* do three */
...
break;
}
and you can get nuts because you assume that, at least one of the possible values of the type should be executed... but that's simply not true, as the variable has not been initialized and the value doesn't need even to comply with the constraints imposed to the data type it represents.
Initializing a variable can introduce a short couple of instructions in your code, but it saves a lot of nightmares when searching for errors.
In the case of an uninitialized pointer, the case is worse, as many programmers free() memory allocated from the heap based on the test
if (var) free(var);
and most probably an uninitialized automatic variable of pointer type will point somewhere, and sill be tried to be free()d.

Is it still undefined behaviour to return a pointer to a local variable when it is wrapped in a struct

So I think that what I got from this post is that it is UB or at least not a good idea to return pointers to locally defined variables, and in fact my compiler gives warning if I do this, however if I wrap the pointer in a struct then the warning no longer shows. Is it still UB or is there something different with structs that makes this OK. I'm using GCC 6.3.0 with -Wall.
Here is an example:
#include <stdio.h>
struct wrapper{
int *ptr;
};
struct wrapper foo(){
int a = 5;
struct wrapper new_wrapper = {&a};
return new_wrapper;
}
int main(){
printf("%d", *foo().ptr); //prints 5, but will it theoretically always do so?
return 0;
}
Returning a pointer is not a problem. The pointer and the object it points to are the problem. Using the pointer by any means is a problem, so wrapping it in a structure does not help.
When an object is “created” automatically inside a function, it is also “destroyed” when execution of the function ends. (In C, creating an object just means reserving memory for it, and destroying it means ending the reservation.)
Additionally, a pointer to memory that is no longer reserved is itself invalid. Although C implementations may implement pointers simply as memory addresses, some C implementations implement pointers in more complicated ways, and releasing the memory reservation may invalidate data needed to make the pointer work. So the C standard says that a pointer becomes invalid when the object it points to is released.
Because of that rule in the C standard, even implementations that implement pointers as memory addresses may treat pointers as invalid when the objects they point to are no longer reserved, with the result that optimization of the program by the compiler may cause any use of an invalid pointer to have unexpected effects.
Yes, it is. The local variable a lives only for the duration of foo.

Memory unallocated pointer variable works. How?

I have written this code & expected it to fail, since I don't allocate memory for the pointer variable. It didn't throw up any error, to my surprise. What is the reason?
And if I, just randomly, delete 2nd LOC, it throws up a segmentation fault. How to explain for this seemingly strange behavior?
uint16_t *c;
uint8_t *d;
*c = 1;
printf("%x:%x",c,*c);
As others have pointed out, it is UB. Your observation of the code "working" in the sense of not causing a segfault or similar is more or less random. Your allocation of another variable on the stack might change where your c pointer is allocated, and thereby it can have a different (random) place it points to. (Or, to put it differently, it's initial random value will or might be different).
Observable different behaviour of a program depending on where and what (independent) objects are allocated within a function are a dead give-away that there is something wrong with memory allocation in the function.

free(struct variable) doesn't clear previous stored values associated with that variable when I malloc again?

I created a struct like the following:
typedef struct header{
int hc;
char src[18];
char dst=[18];
char reason[15];
char d[3];
char m[3];
char y[4];
struct measurements{
char h_ip[17];
int h_ttl;
int h_id;
float h_rtt;
}HOPS[100];
}HEADER;
INSIDE MAIN:
HEADER *head;
for(...){
head=(HEADER*) malloc(sizeof(HEADER));
.....
free(head);
}
Will the above malloc automatically allocate memory for the inner struct as well? Also, I'm facing a weird problem here. After I free the header, I'm still able to print the values of head->HOPS[i].h_ip. Should I explicitly free the inner struct as well so that even the values get cleared?
Yes, it allocates memory for the inner structure. And you need not free the inner structure separately.
If you have a pointer defined inside your structure, in that case you have to allocate separately for that pointer member of the structure and free that separately.
Consider freeing memory as a black box. All what you know is that after freeing you shouldn't refer to freed memory.
You may find that that memory block still exists and still contains some old values. That's ok: it just was marked as freed and probably it will be used again soon by allocator.
For example when you call malloc again and realized that just allocated block contains values from the old structure. It happens and that's alright. Just use this block as usually.
So, after the problem with the wrong declaration of head was resolved:
free returns a previously allocated memory block to the heap. It does not clear anything (for performance reasons). However, you are not supposed to access that block anymore afterwards. Doing so results in undefined behaviour and might let your computer fly out of the window.
Worst that can happen is ... nothing ... Yes, you might even not notice anything strang happens. However, that does not mean your program run correctly, it just does not show any symptoms.
To catch illegal accesses, you might set the pointer to NULL once you freed the object it points to. Some operating systems catch accesses to addresses near the null pointer address, but there is no guarantee. It is a good practice anyway and does no harm.
For your other question: malloc allocates a block of memory large enough to store that many bytes you passed as argument. If it cannot, it will return a null pointer. You should always check if malloc & friends returned a valid pointer (i.e. not a null pointer).
int *p = malloc(sizeof(int));
if ( p == NULL ) {
error: out of memory
}
...
Notice the omission of the cast of the result of malloc. In C you should not cast void * as returned by malloc & friends (but also elsewhere). As much as you did not for free(head). Both take the same type: void *, btw. (so why cast one and not the other?). Note that in C any object pointer can freely be assigned to/from void * without cast. Warning functions are no objects in the C standard!
Finally: sizeof(HEADER) returns the size of the struct. Of course that include all fields. A nested struct is a field. A pointer to another struct is a field. For the latter, however note: the pointer itself is a field, but not what it points to! If that was another struct, you have to malloc that seperately **and also free seperately (remember what I wrote above).
But as you do not have pointer inside your struct, that is not your problem here. (keep it in mind, if you continue programming, you will eventually need that!)

What could be the possible reason behind the warning which comes up when the following piece of code is compiled

This is a simple piece of code which i wrote to check whether it is legitimate to return the address of a local variable and my assumptions were proved correct by the compiler which gives a warning saying the same:
warning: function returns address of local variable
But the correct address is printed when executed... Seems strange!
#include<stdio.h>
char * returnAddress();
main()
{
char *ptr;
ptr = returnAddress();
printf("%p\n",ptr);
}
char * returnAddress()
{
int x;
printf("%p\n",&x);
return &x;
}
The behaviour is undefined.
Anything is allowed to happen when you invoke undefined behaviour - including behaving semi-sanely.
The address of a local variable is returned. It remains an address; it might even be a valid address if you're lucky. What you get if you access the data that it points to is anyone's guess - though you're best off not knowing. If you call another function, the space pointed at could be overwritten by new data.
You should be getting warnings about the conversion between int pointer and char pointer - as well as warnings about returning the address of a local variable.
What you are trying to do is usually dangerous:
In returnAddress() you declare a local, non-static variable i on the stack. Then you return its address which will be invalid once the function returned.
Additionally you try to return a char * while you actually have an int *.
To get rid of the warning caused by returning a pointer to a local var, you could use this code:
void *p = &x;
return p;
Of course printing it is completely harmless but dereferencing (e.g. int x = *ptr;) it would likely crash your program.
However, what you are doing is a great way to break things - other people might not know that you return an invalid pointer that must never be dereferenced.
Yes, the same address is printed both times. Except that, when the address is printed in main(), it no longer points to any valid memory address. (The variable x was created in the stack frame of returnAddress(), which was scrapped when the function returned.)
That's why the warning is generated: Because you now have an address that you must not use.
Because you can access the memory of the local variable, doesn't mean it is a correct thing to do. After the end of a function call, the stack pointer backtracks to its previous position in memory, so you could access the local variables of the function, as they are not erased. But there is no guaranty that such a thing won't fail (like a segmentation fault), or that you won't read garbages.
Which warning? I get a type error (you're returning an int* but the type says char*) and a warning about returning the address of a local variable.
The type error is because the type you've declared for the function is lies (or statistics?).
The second is because that is a crazy thing to do. That address is going to be smack in the middle (or rather, near the top) of the stack. If you use it you'll be stomping on data (or have your data stomped on by subsequent function calls).
Its not strange. The local variables of a function is allocated in the stack of that function. Once the control goes out of the function, the local variables are invalid. You may have the reference to the address but the same space of memory can be replaced by some other values. This is why the behavior is undefined. If you want reference a memory throughout your program, allocate using malloc. This will allocate the memory in heap instead of stack. You can safely reference it until you free the memory explicitly.
#include<stdio.h>
#include<stdlib.h>
char * returnAddress();
main()
{
char *ptr;
ptr = returnAddress();
printf("%p\n",ptr);
}
char * returnAddress()
{
char *x = malloc(sizeof(char));
printf("%p\n",x);
return x;
}

Resources