• No results found

Dynamic Memory Allocation in C using malloc(), calloc(), free() and realloc()

N/A
N/A
Protected

Academic year: 2021

Share "Dynamic Memory Allocation in C using malloc(), calloc(), free() and realloc()"

Copied!
28
0
0

Loading.... (view fulltext now)

Full text

(1)

Page 1 of 28

Dynamic Memory Allocation in C using malloc(), calloc(), free() and realloc()

Since C is a structured language, it has some fixed rules for programming. One of it includes changing the size of an array. An array is collection of items stored at continuous memory locations.

As it can be seen that the length (size) of the array above made is 9. But what if there is a requirement to change this length (size). For Example,

If there is a situation where only 5 elements are needed to be entered in this array. In this case, the remaining 4 indices are just wasting memory in this array. So there is a requirement to lessen the length (size) of the array from 9 to 5.

Take another situation. In this, there is an array of 9 elements with all 9 indices filled. But there is a need to enter 3 more elements in this array. In this case 3 indices more are required. So the length (size) of the array needs to be

changed from 9 to 12.

This procedure is referred to as Dynamic Memory Allocation in C.

Therefore, C Dynamic Memory Allocation can be defined as a procedure in which the size of a data structure (like Array) is changed during the runtime.

C provides some functions to achieve these tasks. There are 4 library functions provided by C defined under <stdlib.h> header file to facilitate dynamic memory allocation in C programming. They are:

1. malloc() 2. calloc() 3. free() 4. realloc()

(2)

Page 2 of 28 Let’s look at each of them in greater detail.

1. C malloc() method

“malloc” or “memory allocation” method in C is used to dynamically allocate a single large block of memory with the specified size. It returns a pointer of type void which can be cast into a pointer of any form. It initializes each block with default garbage value.

Syntax:

ptr = (cast-type*) malloc(byte-size)

For Example:

ptr = (int*) malloc(100 * sizeof(int));

Since the size of int is 4 bytes, this statement will allocate 400 bytes of memory.

And, the pointer ptr holds the address of the first byte in the allocated memory.

If space is insufficient, allocation fails and returns a NULL pointer.

Example:

#include <stdio.h>

#include <stdlib.h>

int main() {

// This pointer will hold the

// base address of the block created int* ptr;

int n, i;

// Get the number of elements for the array n = 5;

(3)

Page 3 of 28 printf("Enter number of elements: %d\n", n);

// Dynamically allocate memory using malloc() ptr = (int*)malloc(n * sizeof(int));

// Check if the memory has been successfully // allocated by malloc or not

if (ptr == NULL) {

printf("Memory not allocated.\n");

exit(0);

} else {

// Memory has been successfully allocated

printf("Memory successfully allocated using malloc.\n");

// Get the elements of the array for (i = 0; i < n; ++i) {

ptr[i] = i + 1;

}

// Print the elements of the array

printf("The elements of the array are: ");

for (i = 0; i < n; ++i) { printf("%d, ", ptr[i]);

} }

return 0;

} Output:

Enter number of elements: 5

Memory successfully allocated using malloc.

The elements of the array are: 1, 2, 3, 4, 5,

2. C calloc() method

“calloc” or “contiguous allocation” method in C is used to dynamically allocate the specified number of blocks of memory of the specified type. It initializes each block with a default value ‘0’.

Syntax:

ptr = (cast-type*)calloc(n, element-size);

For Example:

ptr = (float*) calloc(25, sizeof(float));

This statement allocates contiguous space in memory for 25 elements each with the size of the float.

(4)

Page 4 of 28 If space is insufficient, allocation fails and returns a NULL pointer.

Example:

#include <stdio.h>

#include <stdlib.h>

int main() {

// This pointer will hold the

// base address of the block created int* ptr;

int n, i;

// Get the number of elements for the array n = 5;

printf("Enter number of elements: %d\n", n);

// Dynamically allocate memory using calloc() ptr = (int*)calloc(n, sizeof(int));

// Check if the memory has been successfully // allocated by calloc or not

if (ptr == NULL) {

printf("Memory not allocated.\n");

exit(0);

} else {

// Memory has been successfully allocated

printf("Memory successfully allocated using calloc.\n");

// Get the elements of the array for (i = 0; i < n; ++i) {

ptr[i] = i + 1;

(5)

Page 5 of 28 }

// Print the elements of the array

printf("The elements of the array are: ");

for (i = 0; i < n; ++i) { printf("%d, ", ptr[i]);

} }

return 0;

} Output:

Enter number of elements: 5

Memory successfully allocated using calloc.

The elements of the array are: 1, 2, 3, 4, 5,

3. C free() method

“free” method in C is used to dynamically de-allocate the memory. The

memory allocated using functions malloc() and calloc() is not de-allocated on their own. Hence the free() method is used, whenever the dynamic memory allocation takes place. It helps to reduce wastage of memory by freeing it.

Syntax:

free(ptr);

(6)

Page 6 of 28 Example:

#include <stdio.h>

#include <stdlib.h>

int main() {

// This pointer will hold the

// base address of the block created int *ptr, *ptr1;

int n, i;

// Get the number of elements for the array n = 5;

printf("Enter number of elements: %d\n", n);

// Dynamically allocate memory using malloc() ptr = (int*)malloc(n * sizeof(int));

// Dynamically allocate memory using calloc() ptr1 = (int*)calloc(n, sizeof(int));

// Check if the memory has been successfully // allocated by malloc or not

if (ptr == NULL || ptr1 == NULL) { printf("Memory not allocated.\n");

exit(0);

} else {

// Memory has been successfully allocated

printf("Memory successfully allocated using malloc.\n");

// Free the memory free(ptr);

printf("Malloc Memory successfully freed.\n");

// Memory has been successfully allocated

printf("\nMemory successfully allocated using calloc.\n");

// Free the memory free(ptr1);

printf("Calloc Memory successfully freed.\n");

}

return 0;

}

(7)

Page 7 of 28 Output:

Enter number of elements: 5

Memory successfully allocated using malloc.

Malloc Memory successfully freed.

Memory successfully allocated using calloc.

Calloc Memory successfully freed.

4. C realloc() method

“realloc” or “re-allocation” method in C is used to dynamically change the memory allocation of a previously allocated memory. In other words, if the memory previously allocated with the help of malloc or calloc is insufficient, realloc can be used to dynamically re-allocate memory. re-allocation of memory maintains the already present value and new blocks will be initialized with default garbage value.

Syntax:

ptr = realloc(ptr, newSize);

where ptr is reallocated with new size 'newSize'.

If space is insufficient, allocation fails and returns a NULL pointer.

(8)

Page 8 of 28 Example:

#include <stdio.h>

#include <stdlib.h>

int main() {

// This pointer will hold the

// base address of the block created int* ptr;

int n, i;

// Get the number of elements for the array n = 5;

printf("Enter number of elements: %d\n", n);

// Dynamically allocate memory using calloc() ptr = (int*)calloc(n, sizeof(int));

// Check if the memory has been successfully // allocated by malloc or not

if (ptr == NULL) {

printf("Memory not allocated.\n");

exit(0);

} else {

// Memory has been successfully allocated

printf("Memory successfully allocated using calloc.\n");

// Get the elements of the array for (i = 0; i < n; ++i) {

ptr[i] = i + 1;

}

// Print the elements of the array

printf("The elements of the array are: ");

for (i = 0; i < n; ++i) { printf("%d, ", ptr[i]);

}

// Get the new size for the array n = 10;

printf("\n\nEnter the new size of the array: %d\n", n);

// Dynamically re-allocate memory using realloc() ptr = realloc(ptr, n * sizeof(int));

(9)

Page 9 of 28 // Memory has been successfully allocated

printf("Memory successfully re-allocated using realloc.\n");

// Get the new elements of the array for (i = 5; i < n; ++i) {

ptr[i] = i + 1;

}

// Print the elements of the array

printf("The elements of the array are: ");

for (i = 0; i < n; ++i) { printf("%d, ", ptr[i]);

}

free(ptr);

}

return 0;

} Output:

Enter number of elements: 5

Memory successfully allocated using calloc.

The elements of the array are: 1, 2, 3, 4, 5,

Enter the new size of the array: 10

Memory successfully re-allocated using realloc.

The elements of the array are: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,

(10)

Page 10 of 28

Memory Layout of C Programs

A typical memory representation of C program consists of following sections.

1. Text segment

2. Initialized data segment 3. Uninitialized data segment 4. Stack

5. Heap

When we run any C-program, its executable image is loaded into RAM of computer in an organized manner.

This memory layout is organized in following fashion :-

A typical memory layout of a running process

1>Text or Code Segment :-

Text segment contains machine code of the compiled program. Usually, the text segment is sharable so that only a single copy needs to be in memory for frequently executed programs, such as text editors, the C compiler, the shells, and so on. The text segment of an executable object file is often read-only segment that prevents a program from being accidentally modified.

(11)

Page 11 of 28 2>Initialized Data Segment :-

Initialized data stores all global, static, constant, and external variables ( declared with extern keyword ) that are initialized beforehand. Data segment is not read-only, since the values of the variables can be altered at run time.

This segment can be further classified into initialized read-only area and initialized read-write area.

#include <stdio.h>

char c[]="rishabh tripathi"; /* global variable stored in Initialized Data Segment in read-write area*/

const char s[]="HackerEarth"; /* global variable stored in Initialized Data Segment in read-only area*/

int main() {

static int i=11; /* static variable stored in Initialized Data Segment*/

return 0;

}

3>Uninitialized Data Segment (bss) :-

Data in this segment is initialized to arithmetic 0 before the program starts executing.

Uninitialized data starts at the end of the data segment and contains all global variables and static variables that are initialized to 0 or do not have explicit initialization in source code.

#include <stdio.h>

char c; /* Uninitialized variable stored in bss*/

int main() {

static int i; /* Uninitialized static variable stored in bss */

return 0;

}

(12)

Page 12 of 28 4>Heap :-

Heap is the segment where dynamic memory allocation usually takes place. When some more memory need to be allocated using malloc and calloc function, heap grows upward. The Heap area is shared by all shared libraries and dynamically loaded modules in a process.

#include <stdio.h>

int main() {

char *p=(char*)malloc(sizeof(char)); /* memory allocating in heap segment */

return 0;

}

5>Stack :-

Stack segment is used to store all local variables and is used for passing arguments to the functions along with the return address of the instruction which is to be executed after the function call is over. Local variables have a scope to the block which they are defined in, they are created when control enters into the block. All recursive function calls are added to stack.

The stack and heap are traditionally located at opposite ends of the process's virtual address space.

(13)

Page 13 of 28

Differences between Static and Dynamic Memory Allocation

Sl.No

Static Memory Allocation Dynamic Memory Allocation

1

In the static memory allocation, variables get allocated permanently.

In the Dynamic memory allocation, variables get allocated only if your program unit gets active.

2

Static Memory Allocation is done before program execution.

Dynamic Memory Allocation is done during program execution.

3

Memory is allocated during COMPILE TIME

Memory is allocated during RUN TIME/EXECUTION TIME

4

It uses stack for managing the static allocation of memory

It uses heap for managing the dynamic allocation of memory

5 It is less efficient It is more efficient

6

In Static Memory Allocation, there is no memory re-usability

In Dynamics Memory Allocation, there is memory re-usability and memory can be freed when not required

7

In static memory allocation, once the memory is allocated, the memory size cannot change.

In dynamic memory allocation, when memory is allocated the memory size can be changed.

8

In this memory allocation scheme, execution is faster than dynamic memory allocation.

In this memory allocation scheme, execution is slower than static memory allocation.

9

In this allocated memory remains from start to end of the program.

In this allocated memory can be released at any time during the program.

10 It allocates memory from STACK. It allocates memory from HEAP.

11

Example: This static memory allocation is generally used for array.

Example: This dynamic memory allocation is generally used for linked list.

(14)

Page 14 of 28

Differences between malloc() and calloc()

BASIS OF COMPARISON

MALLOC() CALLOC()

No of blocks Assigns single block of requested memory.

Assigns multiple blocks of the requested memory.

Syntax void *malloc(size_t size); void *calloc(size_t num, size_t size);

Initialization malloc() doesn't clear and initialize the allocated memory.

The allocated memory is initialized to zero by using calloc().

Manner of Allocation malloc() function allocates memory of size 'size' from the heap.

calloc() function allocates memory the size of which is equal to num *size.

Speed Fast Comparatively slow.

(15)

Page 15 of 28

1.What is the return type of malloc() or calloc()?

A. int * B. int **

C. void * D. void **

View Answer Ans : C

Explanation: malloc() and calloc() return void *, without void * we may get warning in C if we don't type cast the return type to appropriate pointer.

2. Which function is used to delete the allocated memory space?

A. Dealloc() B. free()

C. Both a and b D. either a or b View Answer Ans : B

Explanation: free() is used to free the memory spaces allocated by malloc() and calloc().

3.Among 4 header files, which should be included to use the memory allocation functions like malloc(), calloc(), realloc() and free()?

A. #include<string.h>

B. #include<memory.h>

C. #include<stdlib.h>

D. Both b and c View Answer

Ans : C

Explanation: #include<stdlib.h> is a header filer, which contains the inbuilt functions for all memory allocation functions.

4. Which of the following is/are true

A. calloc() allocates the memory and also initializes the allocates memory to zero, while memory allocated using malloc() has random data.

B. malloc() and memset() can be used to get the same effect as calloc() C. Both malloc() and calloc() return 'void *' pointer

D. All of the above View Answer

(16)

Page 16 of 28 Ans : D

Explanation: None

5. Which of the following is true?

A. "ptr = calloc(m, n)" is equivalent to following ptr = malloc(m * n);

B. "ptr = calloc(m, n)" is equivalent to following ptr = malloc(m * n); memset(ptr, 0, m * n);

C. "ptr = calloc(m, n)" is equivalent to following ptr = malloc(m); memset(ptr, 0, m);

D. "ptr = calloc(m, n)" is equivalent to following ptr = malloc(n); memset(ptr, 0, n);

View Answer Ans : B

Explanation:The name malloc and calloc() are library functions that allocate memory dynamically. It means that memory is allocated during runtime(execution of the program) from heap segment.

6. Which languages necessarily need heap allocation in the run time environment?

A. Those that support recursion B. Those that use dynamic scoping C. Those that use global variables

D. Those that allow dynamic data structures View Answer

Ans : D

Explanation:Heap allocation is needed for dynamic data structures like tree, linked list, etc.

7. Which of the following statement is correct prototype of the malloc() function in c ?

A. int* malloc(int);

B. Char* malloc(char);

C. unsigned int* malloc(unsigned int);

D. void* malloc(size_t);

View Answer Ans : D

(17)

Page 17 of 28 Explanation: By defalut for malloc() function return type is void.

8. Specify the 2 library functions to dynamically allocate memory?

A. malloc() and memalloc() B. alloc() and memalloc() C. malloc() and calloc() D. memalloc() and faralloc() View Answer

Ans : C

Explanation:2 library functions to dynamically allocate memory is malloc() and calloc().

9. malloc() returns a float pointer if memory is allocated for storing float's and a double pointer if memory is allocated for storing double's.

A. True B. False View Answer Ans : B

Explanation:malloc() and calloc() return void pointer for using a particular data type we made explicite type casting.

10.malloc() allocates memory from the heap and not from the stack.

A. True B. False View Answer Ans : A

Explanation:Heap area consist of hash codes .i.e. addreses while stack may or may not be that's why malloc() allocates memory from the heap.

(18)

Page 18 of 28 Question 1 − What will be the output of the following code −

#include <stdio.h>

#include <stdlib.h>

int main() {

union my_union { int i;

float f;

char c;

};

union my_union* u;

u = (union my_union*)malloc(sizeof(union my_union));

u->f = 20.60f;

printf("%f", u->f);

}

Options −

Garbage Value

20.600000

Syntax Error

20.6 Explanation

Using unions, we can use same memory location to hold multiple type of data. All member of union uses same memory location which has maximum space. Here float is used, which has 20.60f = 20.600000. So answer B is correct.

Question 2 − What is the correct sequence of the compilation Process − Options −

Assembler, Compiler, Preprocessor, Linking

Compiler, Assembler, Preprocessor, Linking

Preprocessor, Compiler, Assembler, Linking

(19)

Page 19 of 28

Assembler, Compiler, Linking, Preprocessor Explanation −

The option C is correct, At first it preprocess the code, then compile it, after that it creates assembly level code, or object code, then the linking is taken place.

Question 3 − Which of the following statement is true?

Options −

During Linking the Code #include replaces by stdio.h

During Preprocessing the Code #include replaces by stdio.h

During Execution the Code #include replaces by stdio.h

During Editing the Code #include replaces by stdio.h Explanation −

The option B is correct. At first, it creates the preprocessed code, in that phase, it attaches the codes present in file mentioned in #include statements into the code then sent to the compiler.

Question 4 − Purpose of using fflush() function − Options −

To flush all streams and specified streams

To flush only specified streams

To flush input-output buffer

This is invalid library function Explanation −

This function is used to flush output stream only. It clears the output buffer and send the output to the console. The option A is correct.

Question 5 − Point out the error of the following code −

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

int main() {

char* ptr;

*ptr = (int*)malloc(30);

strcpy(ptr, "ABC");

printf("%s", ptr);

(20)

Page 20 of 28

free(ptr);

}

Options −

Error in strcpy() statement

Error in *ptr = (int*)malloc(30);

Error in free(ptr)

No Error Explanation −

The option B is correct. Here this makes integer from pointer, without a cast

(21)

Page 21 of 28

Dangling pointer

A pointer pointing to a memory location that has been deleted (or freed) is called dangling pointer. There are three different ways where Pointer acts as dangling pointer

1. De-allocation of memory

// Deallocating a memory pointed by ptr causes // dangling pointer

#include <stdlib.h>

#include <stdio.h>

intmain() {

int*ptr = (int*)malloc(sizeof(int));

// After below free call, ptr becomes a // dangling pointer

free(ptr);

// No more a dangling pointer ptr = NULL;

}

2. Function Call

// The pointer pointing to local variable becomes // dangling when local variable is not static.

#include<stdio.h>

int *fun() {

(22)

Page 22 of 28 // x is local variable and goes out of

// scope after an execution of fun() is // over.

int x = 5;

return &x;

}

// Driver Code int main() {

int *p = fun();

fflush(stdin);

// p points to something which is not // valid anymore

printf("%d", *p);

return 0;

} Output:

A garbage Address

The above problem doesn’t appear (or p doesn’t become dangling) if x is a static variable.

// The pointer pointing to local variable doesn't // become dangling when local variable is static.

#include<stdio.h>

int *fun() {

// x now has scope throughout the program

(23)

Page 23 of 28 static int x = 5;

return &x;

}

int main() {

int *p = fun();

fflush(stdin);

// Not a dangling pointer as it points // to static variable.

printf("%d",*p);

} Output:

5

3. Variable goes out of scope void main()

{

int *ptr;

...

...

{

int ch;

ptr = &ch;

}

...

// Here ptr is dangling pointer }

(24)

Page 24 of 28

Void pointer

Void pointer is a specific pointer type – void * – a pointer that points to some data location in storage, which doesn’t have any specific type. Void refers to the type.

Basically the type of data that it points to is can be any. If we assign address of char data type to void pointer it will become char Pointer, if int data type then int pointer and so on. Any pointer type is convertible to a void pointer hence it can point to any value.

Important Points

1. void pointers cannot be dereferenced. It can however be done using typecasting the void pointer

2. Pointer arithmetic is not possible on pointers of void due to lack of concrete value and thus size.

Example:

#include<stdlib.h>

int main() {

int x = 4;

float y = 5.5;

//A void pointer void *ptr;

ptr = &x;

// (int*)ptr - does type casting of void // *((int*)ptr) dereferences the typecasted // void pointer variable.

printf("Integer variable is = %d", *( (int*) ptr) );

// void pointer is now float ptr = &y;

(25)

Page 25 of 28 printf("\nFloat variable is= %f", *( (float*) ptr) );

return 0;

} Output:

Integer variable is = 4 Float variable is= 5.500000

NULL Pointer

NULL Pointer is a pointer which is pointing to nothing. In case, if we don’t have address to be assigned to a pointer, then we can simply use NULL.

#include <stdio.h>

int main() {

// Null Pointer int *ptr = NULL;

printf("The value of ptr is %p", ptr);

return 0;

}

Output :

The value of ptr is (nil)

Important Points

1. NULL vs Uninitialized pointer – An uninitialized pointer stores an undefined value. A null pointer stores a defined value, but one that is defined by the environment to not be a valid address for any member or object.

2. NULL vs Void Pointer – Null pointer is a value, while void pointer is a type

(26)

Page 26 of 28

Wild pointer

A pointer which has not been initialized to anything (not even NULL) is known as wild pointer. The pointer may be initialized to a non-NULL garbage value that may not be a valid address.

int main() {

int *p; /* wild pointer */

int x = 10;

// p is not a wild pointer now p = &x;

return 0;

}

(27)

Page 27 of 28

What is memory leak in C?

Memory leak is really a panic, the insufficient memory/ memory resources leaks are know as memory leaks. Memory leak occurs when program does not manage the memory allocation correctly.

Memory leak occurs when programmers create a memory in heap and forget to delete it.

Memory leaks are particularly serious issues for programs like daemons and servers which by definition never terminate.

/* Function with memory leak */

#include <stdlib.h>

void f() {

int *ptr = (int *) malloc(sizeof(int));

/* Do some work */

return; /* Return without freeing ptr*/

}

To avoid memory leaks, memory allocated on heap should always be freed when no longer needed.

/* Function without memory leak */

#include <stdlib.h>;

void f() {

int *ptr = (int *) malloc(sizeof(int));

(28)

Page 28 of 28 /* Do some work */

free(ptr);

return;

}

References

Related documents

With this aversion to the volume of advertising delivered and the suggestion that less frequent and more user controlled advertising is more acceptable, these users are sending

● It's also possible to create references to anonymous variables (similar to allocating memory using malloc in C)?. ● Create a reference to an anonymous array using

Original Malloc Test Pool Malloc Test(map) Pool Malloc Test(nonmap) TC Malloc Test..

Oliver Niggemann, Institute of Industrial IT (inIT), University of Applied Sciences Ostwestfalen-Lippe, 2011. Dynamic memory allocation happens on the heap using the functions

or other electr  onic onic or  or mechanical mechanical methods, without the  methods, without the prior prior wrien wrien permission of the publisher, except permission

Summing up, the simple raw medicinal substances i.e.: non dynamized do not stimulate Biologic Energy as they act in the chemical field and not in the energy field and must be rubbed

The purchase price for Month-Ahead contracts for all delivery days in the entire delivery period is the final settlement price.. The final settlement price is determined on

Comparison of overpressure contour plots for M1 and M3 show that the imposed de- formation leads to an overpressure increase due to tectonic compaction and to the in-