Categories
C language

Frame Pointer

Q- How are variables accessed within a frame in the stack?

Ans: Well as there is a pointer known as stack pointer to manage different operations on stack, the same way there is a frame pointer to access different variables with a frame. The stack pointer points to the top of the stack while the frame pointer points to the starting of the topmost frame as shown:

www.exploreroots.com

Now when the new function is called, the new frame is added in the stack and the frame pointer of the previous frame is saved in this new frame and the frame pointer now contains the starting address of the new frame as shown:

NOTE: We have represented this frame pointer as part of OTHER REGISTERS.

www.exploreroots.com

Similarly if now we have a new function call, then new frame is added in stack and frame pointer of frame ‘abc’ is stored in this new frame and the frame pointer now contains the address of this new function.

How ever when the function returns, the frame address stored in the frame is re-loaded in the Frame Pointer.

Hence Frame Pointer always contains the starting address of the active frame and active frame always contains the frame address of the lower frame.

Categories
C language

Q5: Memory allocation

int main()
{
  int*x;
  x = abc();
  printf(“%d”,*x);
  return 0;
}

int* abc()
{
  int y=3;
  return (&y);
}

As address of the variable y is returned and which gets stored in x and the memory block of function abc() is de-allocated.

www.exploreroots.com

Next we try to store a value in the memory which has been de-allocated. As memory has been de-allocated and hence operating system may have allocated this memory to some other process. Due to this reason referencing to this address may cause an ERROR and hence we better should mark the option of uncertain or can’t say.

SOLUTION: The solution to the above problem can be that if we declare a pointer in place of simple variable and return the address stored in the pointer as:

int* abc()
{
  int* y= malloc(sizeof(int));

  *y=3;
  return (&y);
}
Categories
C language

Q4: Memory Allocation

What is the output of the following code?

int main()
{
  int*x;
  x = abc();
  printf(“%d”,*x);
  return 0;
}

int* abc()
{
  int y=3;
  return (&y);
}
  • (a) 3              (b) 5       (c) Can’t say

Ans: Many would answer it as 3 but it is wrong. The way we have tried to do it is wrong. As we enter into main we have a memory allocated for variable x and then function abc is called.

www.exploreroots.com

Now as function abc() is called, a new frame is added in the stack. We save the return address to main in the stack. Then a variable y is declared.

www.exploreroots.com

Categories
C language

Q3: Memory allocation

Consider the C code

int main()
{
  int x=3;
  fun(x);
  return 0;
}
 

void fun(int n)
{
  n--;
  if (n!=0)
  {

    fun(n);
  }
}

Explain the allocation of memory in stack for the above program.

Ans: firstly a frame in stack is created and memory is allocated to store variable x with value 3.

www.exploreroots.com

And then function call is made to function fun() and a new frame is created in the stack. Firstly return address to main is saved in the stack. Next memory is allocated for variable n and 2 is stored in n.

www.exploreroots.com

Now n—is executed and n becomes 1. Then if statement is executed and another call to fun() is made and value 1 is passed. Again return address to function Fun() is saved and then value 1 is stored in variable n. execution of n- – decreases the value to 0.

www.exploreroots.com

Q-Why do sometimes we encounter an error named as ‘Stack Overflow ERROR’?

Ans: It occurs due to the infinite recursion calling. As we can see in the above case that in case of recursion (when a function calls itself), everyt ime a function is called new memory is allocated in the stack and hence in case of infinite incursion, a function is called infinite times and hence memory is allocated infinite times and hence we fall in shortage of memory in stack which is STACK OVERFLOW.

Now we have the next statement as if statement whose condition goes wrong as value of n is zero and hence no function call is made. After this we face a closed parantesis which means function is returned to the address saved in the address register.

www.exploreroots.com

Now we are in the function Fun() which was called first. Next statement in this function is also a closed parenthesis. Hence function again gets returned.

www.exploreroots.com

Now the main ends and program execution ends and hence whole stack is de-allocated and whole stack becomes empty

www.exploreroots.com

Categories
C language

Q2: Memory Allocation

Consider the C code:

int a = 2;

int main()

{

 int x= func2(5);

 printf(“%d”, x);

 return 0;

}


int func1(int n)

{

 int p;

 p= a*n*n;

 printf(“%d”, p);

 return 3;

}


void func2(int n)

{

 int k;

 func1(n) ;

 k=func1(2*n);

 printf(“%d”,k);

 return 7;
}

Now we have to picturize the whole scenario in HEAP and STACK memory.

Ans: We have no dynamically allocated variables in this program. Hence there is not much role of HEAP memory. We analyze the memory allocation and de-allocation in STACK on next page. We know stack memory is used to store local variables and the return address pointer, frame pointer (the pointer which is used to point to the starting of the frame just below) and other registers.

The global variable ‘a’ with value 2 is stored in the fixed memory and the memory remains allocated till the program execution ends.

Now as we enter into main, a frame is created in the stack. Next with the statement int x= func2(5), memory is reserved for the local variable x in the stack.

www.exploreroots.com

Now we have a function call to function func2 hence a new frame is created and firstly return address to main is stored in the stack. Next we have to allocate a space for variable n which is a parameter of the function func2() and 5 is stored. After this another local variable k is allocated space in stack with random value.

www.exploreroots.com

Now we make a function call to func1(). Hence a new frame is created in the stack and n=5 is passed as parameter. Firstly return address to the function func2() is saved on stack. Next space is allocated to variable n and given value 5. This variable n is different from the variable n in the function func2() although they have same names but different addresses. Now we have the statement int p; i.e.  again memory is allocated for another local variable p and random value is there in the memory. After this the statement p=x*n*n evaluates tostore a value 2*5*5 = 50.

www.exploreroots.com

After this value of p is printed and value 3 gets returned. As the function func1 ends & returns to the address stored in the address register and hence its frame is de-allocated memory and memory map of stack is as:

www.exploreroots.com

Now we are in the function func2(). Next statement we have is k=func1(2*n); Hence a function call to func1 is made with parameter 2*5=10 and a new frame is created. In the func1 function firstly return address to func2 function is saved along with other registers. Next space is allocated to variable n and given value 10. This variable n is different from the variable n in the function func2() although they have same names but different addresses. Now we have the statement int p; i.e. again memory is allocated for another local variable p and random value is there in the memory. After this the statement p=x*n*n evaluates tostore a value 2*10*10 = 200.

www.exploreroots.com

Now value of p is printed and 3 gets returned and stored in variable k in function func2.

www.exploreroots.com

After this value of k gets printed and value 7 is returned. The function func2 returns to main and 7 gets stored in x.

www.exploreroots.com

After this value of x is printed and program ends. And hence the whole stack is de-allocated and even global variable ‘a’ is de-allocated.

www.exploreroots.com

Categories
C language

Q1: Memory allocation

Now we have the following statements and we see how STACK & HEAP memory is allocated to different variables. We have the empty HEAP memory & STACK memory as:

NOTE: For this question we have used a heap memory & allocated space serially while in real, memory is allocated randomly by operating system.

www.exploreroots.com

char* x;

x= (char*)malloc(2);

char* y= (char*)malloc(4);

free(x);

char* z= (char*)calloc(3, sizeof(char));

free(y);

free(z);

Now we represent the HEAP and STACK memory after each statement.

char* x;

Assuming X would occupy 4-bytes for storing address. Hence 4 bytes are allocated for x in the STACK but only some random value that is already preset at the allocated memory gets stored in the pointer.

www.exploreroots.com

x= (char*)malloc(2);

With this instruction, firstly 2 bytes are allocated from the HEAP and then the starting address of the allocated memory is stored in the pointer x but the values stored in the memory allocated are random. Now note that in the pointer there is no information stored about where the allocated memory ends. So how would we know where the memory ends while accessing memory? Actually we can’t know the end. The programmer has to take care of himself otherwise it’ll cause ERROR. While storing characters a NULL character ’\0’ is stored to detect the end of memory.

www.exploreroots.com

Char* y= (char*)malloc(4);

Similar to the above case, 4 bytes are allocated for the pointer in the STACK and then the 4 bytes are allocated from HEAP and starting address is stored in the pointer.

www.exploreroots.com

free(x);

www.exploreroots.com

Now there ia no memory allocated to the pointer x and hence if now we try to use the memory then it may cause ERROR as we’ll referencing to the deallocated memory. Now one may ask that what the problem in referencing that memory is. Actually as we have de-allocated the memory, the operating system can allocate that space to some other proess and then if we refer to that space then it may cause a serious ERROR. HOW CAN WE AVOID THIS PROBLEM? We can avoid this problem by putting NULL to the pointer after de-allocating the memory as shown:

free(x);

x= NULL; So that now if we mistakenly try to refer to the memory then it causes no serious problem.

Char* z= (char*)calloc(3, sizeof(char));                         SIZE OF CHAR WE TAKE AS 1 BYTE.

calloc() function is same as malloc() but it also initializes the allocated memory to zero. Hence 3 bytes are allocated from the HEAP memory and zero (0) is stored in the allocated memory 2006 – 2008 and starting address is stored in the pointer z.

www.exploreroots.com

free(y);

The memory allocated to pointer y is freed and hence that memory is available for re-use.

www.exploreroots.com

free(z);

The memory allocated to pointer z is freed and hence that memory is available for re-use.

www.exploreroots.com

The STACK memory would be freed when the function containing the above statements returns or if statements are in the main () function, then the memory in the STACK would be freed when the program ends.

Categories
C language

Functions to manage heap memory

The functions to manage heap memory which are included in the directory  #include <stdlib.h> are:

 malloc():

void * malloc (size_t size);

As we see from the prototype of the malloc function that we have to pass the number of bytes required as parameter to the malloc function and the function returns the starting address of the allocated apace as void pointer. As the void pointer is returned hence we have to typecast the pointer as the type we require. E.g.

If we need 6 bytes for intergers we type cast the memory as

Int* x;

x=(int*)malloc(6);

If we are storing char variables in the allocated space then we do as:

Char* y;

y=(char*)malloc(6);

calloc():

The prototype of the function is as:

void * calloc (size_t nr, size_t size);

nr is number of variables of the required type and size is the number of bytes required for that type

and this function automatically initializes the memory allocated to zero.

e.g.

if we need memory for 6 integers

int* x;

x=(int*)calloc (6, sizeof(int) );

 if we need memory for 6 characters

char* x;

x=(char*)calloc (6, sizeof(char) );

NOTE: If any of the two functions is not able to allocate memory then it returns a NULL pointer.

realloc():

The prototype of the realloc() function is

void * realloc (void *ptr, size_t size);

This function is used to redefine the size already allocated. Suppose as I have already allocated memory for 6 integers in the previous example, now I want the space for the 8 integers then I do as:

X= (int*)realloc (x,8) ;

Free():

The prototype of the free() function is

void* free (void* ptr);

We write the following to free the memory of x:

free(x);

Categories
C language

Program Memory – Introduction

This article is very important for the person who wants to understand c language. Anyone who is going for any interview for a good software company must read the following article as the questions asked in the tests and interviews need the candidate to be clear in the following concepts. This article would ensure that the answers to the following questions are answered properly:

How are variables and pointers actually represented at the machine level?

What is the reason behind the dangling pointers?

Why do the dereference error occurs?

Why do we have other bugs on pointers?

Hence I recommend every person who wants to have a good understanding to read this article. I have explained concepts by transforming them into the form of questions. The article has been written in such a way that it becomes very simple for the user to understand this.

In C language we have different types of variables like global variable, local variable, parameter to the function and dynamically allocated variable.

 But do we know how memory is allocated to these variables and where are these variables stored?

This concept is very important to understand. So let’s discuss this and understand the language better which would help us in dealing with many errors in the program.

We consider 3 kinds of memory in a computer system

FIXED MEMORY:

This memory is used to store the program written or the application being run (i.e. the executable code) and the constant variables or other constant structures. The global and the static variables are also stored in the fixed memory.   This memory is categorized into code memory, data memory etc. The code memory stores the executable code while the data memory stores the global and the static variables.

STACK MEMORY:

The stack memory is a data structures which follows the policy of Last In First Out (LIFO).The stack memory is used to store the static data which includes the variables which are declared at the start of the program like the fixed arrays, local variables and the parameters which are passed to a function during the function call. Other than this the return address pointer, frame pointer (the pointer which is used to point to the starting of the frame just below) and other registers. The life of the static variables ends as soon as the function returns or the program execution stops. The stack memory is used separately for separate programs in an operation system. The memory in stack is allocated at the compile time.

Disadvantage: The memory declared first remains the same i.e. if we declare large memory then there is wastage of memory while if we declare lesser memory then we are in a problem.

Advantage: The memory allocated is deallocated automatically after the function returns and hence the same memory is available for re-use again.

HEAP MEMORY

The heap memory is used to allocate space to the dynamic data. The data whose size can shrink and expand as the requirements vary. We can allocate the extra memory whenever required using command such as malloc(), calloc(), realloc() and de-allocate the space already allocated using command such as free(), delete(). The memory in heap is allocated at the run time.

Wecan take HEAP memory as a group of nodes (circles) and every node is reachable only if It has a direct or indirect reference from some root node (pointer) which is stored in STACK memory. When we use memory allocation functions like malloc, calloc or realloc the memory node are selected and linked to the specified root node. Now if we don’t free the nodes of HEAP memory before the root node is de-allocated, the reference to those memory nodes is lost and they become unreachable, hence known as garbage memory or memory leak. Hence to avoid this problem the programmer must free the memory after it’s use.

Advantage: This memory can be anytime shrunk or expanded when ever the requirements of the program changes.

Disadvantage: We have to manually deallocate the memory allocatd using function like free or delete, otherwise the memory which is not deallocated at the proper time goes to the garbage and is not available for re-use.

We can represent the above memories in a diagram as

www.exploreroots.com

Example

Consider the program

int x=4;

main()
{
    int z;
    char* y;
    y= malloc(6);
    y = "Hello";
    printf(“%c”, *y);
    z = square(x);

    printf(“%d”, z);

    free(y);

}

int  square(Int k)
{
    return k*k;
}

 Now we see which variables in the program are stored where.

In this program we have different types of variables like x as global variable, z & k as local variable and as parameter to the function and y is dynamically allocated variable. So x is stored in fixed memory, z & k are stored in Stack Memory and the pointer y is also stored in stack memory while the 6 bytes (allocated by malloc) which are pointees of pointer y are stored in heap memory.

Categories
C language

NULL pointer

It is the simplest pointer. The NULL pointer is a pointer which points to no where.. We can also use integer 0 in place of constant NULL.

www.exploreroots.com

Int* x=NULL;

The above statement creates a NULL pointer x.

DEREFERENCING NULL

As we know NULL pointer is actually a pointer which points to nowhere and hence we can not dereference to the NULL pointer. It is a run time ERROR to point to the NULL pointer.

Int* x=NULL;

*x=3;     DEREFERENCING NULL ERROR

After execution of statement 1, in the memory map x can be described as follow:

www.exploreroots.com

Now if we try to execute statement2, which actually is trying to assign value to the pointee of the ponter x. But as we know, the above declared pointer has no pointee, hence now we can recognize an ERROR in the above set of statements and the ERROR is called DEREFERENCING NULL

DANGLING POINTER:

The dangling pointer ERROR is an error in which we try to dereference to a memory place which has not been allocated yet.

Int* x;

*x=3;     DANGLING POINTER ERROR

After execution of statement 1, in the memory map x can be described as follow:

www.exploreroots.com

As till now we have allocated no pointee to the pointer and still we are try to dereference. As there is a random address stored in the pointer, hence if we dereference it now then we may dereference a wrong memory and hence may even corrupt some crucial application.

How ever if we only try to print the value *x then there are no chances of corrupting any application and hence it would not cause much harm but still an erroneous output. It is also called bad pointer bug.

REFERENCING DE-ALLOCATED MEMORY:

This problem occurs when the address of the local variable is returned from a function or the programmer deletes the allocated memory mistakedly.

main()

{

Int *y=abc();

*y=3;     A SERIOUS BUG (You’ll get the full explanation in the article Memory Management)

}

Int* abc()

{

Int x=7;

return (&x);

}

After the execution of statement1 in the main, the memory map is as:

www.exploreroots.com

Now we have reached the function abc (), the execution of statement1 of function abc() results into following memory map:

www.exploreroots.com

But when the function abc() returns, the address of the variable x is stored in y and INTENTION is to use x as pointee of y. But with the return of the function abc(), the stack frees the variable x. Hence memory location of x can be used somewhere else by the Operating System.

www.exploreroots.com

The non-belonging memory is the memory which doesn’t belong to the program anymore. Hence the situation now is similar to the DANGLING POINTER case. Hence the 2nd statement of main() may cause ERROR.

Note: REFER TO THE ARTICLE MEMORY MANAGEMENT FOR BETTER UNDERSTANDNG

Categories
C language

Pointer arithmetic

Addition of a number to pointer: Pointer+ number

When we add some integer to the pointer then the address stored in the pointer is incremented by         

                        number * sizeof (datatype of pointer)

Assume space required for data types int & char are 2 & 1 bytesresp.

And we represent a particular block of memory filled with random values (not shown) as:

www.exploreroots.com

If we declare the pointers as

int *x:

int *y:

int i=3;// starting address of i is 9 and is 2 byte wide.

x=&i;

printf(“value at x is %d”, *x); // output we get is 3 i.e. value stored at location 9 & 10    

x=x+1; // now x points to space with starting address 11

printf(“value at x is %d”, *x); // output we get is a random value i.e. value stored at location 11 & 12

x=x+3; // we add 3*2=6 more i.e. now x points to address 17

printf(“value at x is %d”, *x); // output we get is a random value i.e. value stored at location 17 & 18

If we declare the pointers as

char *x:

char *y:

char i // starting address of i is 9 and is 1 byte wide.

x=&i;

printf(“value at x is %d”, *x); // output we get is the value stored at location 9

x=x+1; // we add 1*1=1 and now x points to space with starting address 10

printf(“value at x is %d”, *x); // output we get is a random value i.e. value stored at location 10

x=x+3; // we add 3*1=3 more i.e. now x points to address 13

Subtraction of a number from the pointer :      Pointer- number

When we subtract some integer from the pointer then the address stored in the pointer is decremented by         

                        number * sizeof (datatype of pointer)

Assume space required for data types int & char are 2 & 1 bytesresp.

And we represent a particular block of memory filled with random values (not shown) as:

www.exploreroots.com

If we declare the pointers as

int *x:

int *y:

int i=3;// starting address of i is 9 and is 2 byte wide.

x=&i;

printf(“value at x is %d”, *x); // output we get is 3 i.e. value stored at location 9 & 10    

x=x-1; // now x points to space with starting address 7

printf(“value at x is %d”, *x); //output we get is random value i.e. value stored at location 7& 8h

x=x-3; // we subtact 3*2=6 more i.e. now x points to address 1

printf(“value at x is %d”, *x); // output we get is random value i.e. value stored at location 1&2

If we declare the pointers as

char *x:

char *y:

char i // starting address of i is 9 and is 1 byte wide.

x=&i;

printf(“value at x is %d”, *x); // output we get is the value stored at location 9

x=x-1; // we subtract 1*1=1 and now x points to space with starting address 8

printf(“value at x is %d”, *x); // output we get is a random value i.e. value stored at location 10

x=x-3; // we subtract 3*1=3 more i.e. now x points to address 7

Subtraction of two pointers:          Pointer – Pointer

When we subtract two pointers, we get the number of variables of datatype as same as pointer that are stored between the two pointers.

If we use int pointers:

int *x;

int*y;

int i=1;

int y=2;

int d;

Suppose address of i is 3432 and that of j is 4456 and int requires 2 bytes

x=&I;

y=&j;

d= y –x; // answer get is (4456 – 3432)/2 = 1024/2 = 512.

// we divide by 2 as int takes 2 bytes

If we use char pointers:

 char *x;

char*y;

char i;

char y;

char d;

Suppose address of i is 3432 and that of j is 4456 and char requires 1 bytes

x=&I;

y=&j;

d= y –x; // answer get is (4456 – 3432)/1 = 1024/1 = 1024.

// we divide by 1 as char takes 1 bytes

All other types of operations on pointers like addition of pointersmultiplying pointer by numberdividing pointer by number are illegal.