Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic memory allocation in 'c' Issues

I was writing a code using malloc for something and then faced a issue so i wrote a test code which actually sums up the whole confusion which is below::

# include <stdio.h>
# include <stdlib.h>
# include <error.h>

int main()     
{
     int *p = NULL;
     void *t = NULL;
     unsigned short *d = NULL;

     t = malloc(2);
     if(t == NULL) perror("\n ERROR:");
     printf("\nSHORT:%d\n",sizeof(short));
     d =t;
     (*d) = 65536;
     p = t; 
     *p = 65536;
     printf("\nP:%p: D:%p:\n",p,d);
     printf("\nVAL_P:%d ## VAL_D:%d\n",(*p),(*d));
     return 0;
  }
   Output:: abhi@ubuntu:~/Desktop/ad/A1/CC$ ./test

            SHORT:2
            P:0x9512008: D:0x9512008:
            VAL_P:65536 ## VAL_D:0

I am allocating 2 bytes of memory using malloc. Malloc which returns a void * pointer is stored in a void* pointer 't'.

Then after that 2 pointers are declared p - integer type and d - of short type. then i assigned t to both of them*(p =t and d=t)* that means both d & p are pointing to same mem location on heap.

on trying to save 65536(2^16) to (*d) i get warning that large int value is truncated which is as expected. Now i again saved 65536(2^16) to (*p) which did not caused any warning.

*On printing both (*p) and (d) i got different values (though each correct for there own defined pointer type).

My question are:

  1. Though i have allocated 2 bytes(i.e 16 bits) of heap mem using malloc how am i able to save 65536 in those two bytes(by using (p) which is a pointer of integer type).?? i have a feeling that the cause of this is automatic type converion of void to int* pointer (in p =t) so is it that assigning t to p leads to access to memory regions outside of what is allocated through malloc . ??.

  2. Even though all this is happening how the hell derefrencing the same memory region through (*p) and (*d) prints two different answers( though this can also be explained if what i am thinking the cause in question 1).

Can somebody put some light on this, it will be really appreciated..and also if some one can explain the reasons behind this..

Many thanks

like image 545
abhi Avatar asked Oct 24 '22 01:10

abhi


2 Answers

Answering your second question first:

The explanation is the fact that an int is generally 4 bytes, and the most significant bytes may be stored in the first two positions. A short, which is only 2 bytes, also stores its data in the first two positions. Clearly, then, storing 65536 in an int and a short, but pointing at the same memory location, will cause the data to be stored offset by two bytes for the int in relation to the short, with the two least significant bytes of the int corresponding to the storage for the short.

Therefore, when the compiler prints *d, it interprets this as a short and looks at the area corresponding to storage for a short, which is not where the compiler previously stored the 65536 when *p was written. Note that writing *p = 65536; overwrote the previous *d = 65536;, populating the two least significant bytes with 0.

Regarding the first question: The compiler does not store the 65536 for *p within 2 bytes. It simply goes outside the bounds of the memory you've allocated - which is likely to cause a bug at some point.

like image 138
Dan Nissenbaum Avatar answered Oct 30 '22 21:10

Dan Nissenbaum


In C there is no protection at all for writing out of bounds of an allocation. Just don't do it, anything can happen. Here it seems to work for you because by some coincidence the space behind the two bytes you allocated isn't used for something else.

like image 23
Jens Gustedt Avatar answered Oct 30 '22 22:10

Jens Gustedt