This following code works fine:
#include <stdio.h>
#include <stdlib.h>
int main()
{
struct node{
int a, b, c, d, e;
};
struct node *ptr = NULL;
printf("Size of pointer ptr is %lu bytes\n",sizeof (ptr));
printf("Size of struct node is %lu bytes\n",sizeof (struct node));
ptr = (struct node*)malloc(sizeof (ptr)); //Line 1
// ptr = (struct node*)malloc(sizeof (struct node)); //Line 2
ptr->a = 1; ptr->b = 2; ptr->c = 3; ptr->d = 4; ptr->e = 5;
printf("a: %d, b: %d, c: %d, d: %d, e: %d\n",
ptr->a,ptr->b,ptr->c,ptr->d,ptr->e);
return 0;
}
When complied as:
gcc -Wall file.c
My question is: why is this fine?
malloc
allocates the number of bytes which are specified in it's argument. Here sizeof ptr
is 8 bytes on my 64-bit linux machine. I thought malloc
will provide 8 bytes but then how is it accessing all the variables a,b,c,d,e? Is it with gcc only or am I missing something with standard C?
As far as I know "Line 2" should be there instead of "Line 1" but either of the line works fine. Why?
You have undefined behavior here.
malloc
will allocate 8 bytes (as you say), but this cast is "bad":
ptr = (struct node*)malloc(sizeof (ptr));
After this line, ptr
will point to a memory block, which has only 8 allocated bytes, the rest are some "random" bytes. So, making
ptr->a = 1; ptr->b = 2; ptr->c = 3; ptr->d = 4; ptr->e = 5;
you actually change some memory, not only the allocated by malloc
.
In other words, you are rewriting memory, you're not supposed to touch.
Line 1 is incorrect and won't allocate sufficient space. If you can access the structure members later it is only because C does nothing to prevent you from accessing memory that doesn't belong to you.
Accessing ptr->b
, ptr-c
, etc., when you haven't allocated enough space for the entire structure is undefined behavior, and the next time that you run your code it could crash, or you could end up overwriting data in another part of your program.
To demonstrate the problem, allocate a second struct node
immediately after the first. This isn't guaranteed to demonstrate the problem, but you're likely to see results similar to the following:
struct node *ptr = NULL;
struct node *ptr2 = NULL;
ptr = (struct node*)malloc(sizeof (ptr)); // Your Line 1
ptr2 = malloc(sizeof(struct node)); // alloc another struct on the heap
ptr->a = 1; ptr->b = 2; ptr->c = 3; ptr->d = 4; ptr->e = 5;
ptr2->a = 11; ptr->b = 12; ptr->c = 13; ptr->d = 14; ptr->e = 15;
printf("ptr: a: %d, b: %d, c: %d, d: %d, e: %d\n",
ptr->a, ptr->b, ptr->c, ptr->d, ptr->e);
printf("ptr2: a: %d, b: %d, c: %d, d: %d, e: %d\n",
ptr2->a, ptr2->b, ptr2->c, ptr2->d, ptr2->e);
Output:
ptr: a: 1, b: 2, c: 3, d: 4, e: 11
ptr2: a: 11, b: 12, c: 13, d: 14, e: 15
Note that ptr->e
has been modified by the assignment to ptr2->a
, so you can see that one improperly-allocated structure is stepping on the memory of another. This certainly isn't what you want.
malloc
is allocating only 8 bytes, but that doesn't stop you accessing memory beyond that. You will probably corrupt the heap and might write over other objects. The behaviour of the program is undefined.
In ptr->a = 1; ptr->b = 2; ptr->c = 3; ptr->d = 4; ptr->e = 5;
you are accessing beyond the memory allocated by the malloc.
This is a case of buffer overflow and causes undefined behaviour
.
It is possible because
C and C++ provide no built-in protection against accessing or overwriting data
in any part of memory.
so, it may work sometime, sometime it may crash the program also.