Skip to content

Commit

Permalink
added day-12 content in the docs section, also added the related imag…
Browse files Browse the repository at this point in the history
…es in the static folder. Have checked by running the project locally, it is working as expected. (#291)

Co-authored-by: Shubhadip Bhowmik <[email protected]>
  • Loading branch information
parmarshashank and subhadipbhowmik authored Jun 13, 2024
1 parent 69c2be0 commit b4da883
Show file tree
Hide file tree
Showing 7 changed files with 243 additions and 2 deletions.
5 changes: 3 additions & 2 deletions docs/day-11/reference-in-cpp.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ description: "In this tutorial, we will learn about Reference in C++ programming
sidebar_label: "Reference"
slug: reference-in-cpp
---
## Reference in C++
![String in CPP](../../static/img/day-11/reference-in-cpp.png)

## 1. What is a Reference in C++?

Expand Down Expand Up @@ -54,6 +52,9 @@ int main() {
}
```

![String in CPP](../../static/img/day-11/reference-in-cpp.png)


## 5. How to Pass a Reference to a Function in C++?

To pass a reference to a function, you use the same `&` syntax in the function parameter list. This allows the function to modify the original variable.
Expand Down
102 changes: 102 additions & 0 deletions docs/day-12/dma-in-cpp.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
---
sidebar_position: 2
title: "Dynamic Memory Allocation in C++"
description: "In this tutorial we will apply the concept of dynamic memory allocation in C++. The purpose of this tutorial is to explore how the new and delete works in C++."
sidebar_label: "Dynamic Memory Allocation in C++"
slug: dma-in-cpp
---
C++ provides two primary operations for Dynamic memory allocation:
* Allocating the memory using the `new` keyword.
* De-allocating the previously allocated memory using the `delete` keyword.

## 1. Allocating memory using the `new` keyword

The new keyword in C++ is used for dynamic memory allocation. It allows you to allocate memory for variables or objects during runtime.
### Memory Allocation
When you use `new`, memory is allocated from the heap. The heap is a region of memory that is managed by the operating system, and it's separate from the stack memory where local variables are typically stored.
The new operator returns a pointer to the memory location where the new object or variable is stored.

If the memory allocation fails (e.g., due to insufficient memory), new throws a `std::bad_alloc` exception.

### Syntax for using the `new` keyword
The syntax for the `new` keyword is:
```
data_type *ptr_name= new data_type;
```
![dma-in-cpp](../../static/img/day-12/dmaInCpp.png)

## 2. Deallocating the previously allocated memory using the `delete` keyword

The `delete` keyword in C++ is used to deallocate memory that was allocated dynamically using the new keyword.

### Matching Allocation and Deallocation
*When you dynamically allocate memory using `new`, you must deallocate it once it's no longer needed to prevent memory leaks. `delete` is used to perform this deallocation.

Memory allocated with new persists until explicitly deallocated. Therefore it is necessary to match the `new` keyword with `delete`.

### Syntax for using the `delete` keyword
To delete an allocated memory we can simply use the `delete` keyword with the pointer pointing to the allocated memory.

* For deallocating memory for a single object: `delete pointer;`
* For deallocating memory for an array of objects: `delete[] pointer;`

#### Example
```
int *ptr = new int; // Allocate memory
delete ptr; // Deallocate memory
```
Attempting to delete a null pointer (a pointer that doesn't point to any valid memory address) has no effect. It's safe to delete a null pointer.

Deleting a pointer that was not allocated with `new` leads to undefined behavior.

Accessing memory through a pointer after it has been deleted results in undefined behavior. It may lead to a crash, or the program may appear to work correctly despite accessing invalid memory.

## 3. Examples
Example C++ program that takes the number of elements as input from the user and creates an array using Dynamic Memory Allocation (DMA).

```
#include <iostream>
using namespace std;
int main() {
int n;
// Ask the user to enter the number of elements
cout << "Enter the number of elements: ";
cin >> n;
// Dynamically allocate memory for an array of integers
int *arr = new int[n];
// Input values into the array
cout << "Enter " << n << " integers:" << std::endl;
for (int i = 0; i < n; ++i) {
cin >> arr[i];
}
// Display the elements of the array
cout << "Elements of the array:" << endl;
for (int i = 0; i < n; i++) {
cout << arr[i] << " ";
}
// Deallocate memory
delete[] arr;
return 0;
}
```
### Output:
```
Enter the number of elements: 5
Enter 5 integers:
1
2
3
4
5
Elements of the array:
1 2 3 4 5
=== Code Execution Successful ===
```



79 changes: 79 additions & 0 deletions docs/day-12/introduction-to-dma.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
---
sidebar_position: 1
title: "Introduction to Dynamic Memory Allocation"
description: "In this tutorial we will explore what dynamic memory allocation is and What is it used for. We will see how dynamic memory allocation is different from static memory allocation"
sidebar_label: "Introduction to Dynamic Memory Allocation"
slug: introduction-to-dma
---
## 1. What is Dynamic Memory Allocation?
Dynamic memory allocation is a part of memory management techniques in C++. Dynamic memory allocation allows a user to allocated memory at runtime, during the execution.

DMA empowers C++ programs to request memory from the operating system as needed during runtime. This is particularly useful when the size of data structures isn't known at compile time or needs to adjust dynamically throughout the program's execution. Unlike static memory allocation on the stack (fixed size), DMA leverages the heap, a more flexible memory region that expands and contracts as required.

![Introduction-to-DMA](../../static/img/day-12/introduction.png)

## 2. Need of Dynamic Memory Allocation
The question might arise that why do we need Dynamic Memory allocation and what are the benefits of doing so.

#### The advantages of Dynamic Memory Allocation are:

* **Flexibility**: It empowers you to allocate memory for data structures whose exact size is unknown until runtime. This is particularly useful for user input, reading data from files, or creating complex data structures like linked lists and trees that require dynamic memory allocation.

* **Efficiency**: DMA promotes memory usage efficiency by allocating memory only when it's truly needed. This is beneficial for scenarios where data might not be used throughout the entire program, preventing memory waste.

* **Scalability**: DMA excels at handling data structures that exhibit dynamic size changes during program execution. This makes it ideal for situations where you need to grow arrays, resize collections, or process data of varying sizes.

## 3. Problem with Static Memory Allocation

### **Fixed Sizes at Compile Time**
Once intialized, it is not possible to increase or decrease the size of the data structure we are using.

**For Example**
```
#include <iostream>
using namespace std;
int main() {
int numbers[5];
cout << "Enter 10 numbers: ";
for (int i = 0; i < 10; i++) {
cin >> numbers[i];
}
}
```
In the code above, we have initialized an integer array 'numbers' of size 5, however at during the runtime we are prompting user to enter 10 elements, this will result in a **buffer overflow error** because we are trying to access an index postion that does not exist in the array.

### Memory Wastage
In case the programmer does not know about the required size of the structure in advance, static memory allocation often leads to wastage of memory.

**For Example**
```
#include<iostream>
using namespace std;
int main(){
int numbers[1000];
int n;
//taking the number of elements as input from the user
cout << "Enter the number of Elements to be enters in the array" << endl;
cin >> n;
for(auto i=0; i < n; i++)
cin >> numbers[i];
return 0;
}
```
In the above example, as the programmer does not know how many elements the user is going to enter at runtime, to be on the safe side one often declares a structure of size much greater than required i.e 1000 in this example.

Let's say the user enters only 5 elements at the runtime, the space of other 995 elements or memory location then gets wasted as those memory blocks are reserved for the array of size 1000 elements and thus cannot be reused by any other structure.

This phenomenon is often called **Internal Fragmentation**. Internal fragmentation occurs when a statically allocated data structure (like an array or struct) wastes some space within its allocated block. This wasted space cannot be used by other variables because the entire block is reserved for that specific data structure.










59 changes: 59 additions & 0 deletions docs/day-12/problems-in-dma.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
---
sidebar_position: 3
title: "Problems due to dynamic memory allocation"
description: "In this tutorial we will apply the concept of dynamic memory allocation in C++. The purpose of this tutorial is to explore how the new and delete works in C++."
sidebar_label: "Problems due to dynamic memory allocation in C++"
slug: problems-in-dma
---

## 1. Memory Leakage
Memory leakage in C++ occurs when memory that is allocated dynamically is not deallocated properly, leading to a loss of memory that cannot be reused by the program. This can result in inefficient memory usage and can eventually cause the program to run out of memory. Memory leaks can be a significant issue, especially in long-running programs or systems where memory resources are limited.

### Failure to Deallocate Dynamically Allocated Memory:
When memory is allocated using the keywords like `new` it is the responsibility of the programmer to deallocate the assigned memory after it is no longer needed, failure in doing so might lead to the memory leakage problem.

```
int main() {
int *ptr = new int; // Allocate memory
// No deallocation of memory
return 0;
}
```
### Losing the pointer to Dynamically allocated memory
If the memory is allocated dynamically and pointer which is storing the address of the assigned memory gets overwritten without proper deallocation of the allocated memory it leads to memory leakage.

```
int main() {
int *ptr = new int; // Allocate memory
ptr = nullptr; // overwriting and losing the reference of allocated memory
return 0;
}
```
![Introduction-to-DMA](../../static/img/day-12/problems.png)

## 2. Dangling pointers
Dangling pointers are pointers that point to memory that has been deallocated, freed, or otherwise invalidated. Accessing or dereferencing a dangling pointer can lead to undefined behavior, crashes, or unexpected results.

When memory allocated using new is deallocated using delete, any pointers pointing to that memory become dangling pointers. If these pointers are accessed or dereferenced after deallocation, it leads to undefined behavior.

```
int* ptr = new int; // Allocate memory
delete ptr; // Deallocate memory
// ptr becomes a dangling pointer
```
After memory is deallocated, it can be reused for other purposes. If a dangling pointer is dereferenced after deallocation, it might accidentally access unrelated data stored in the same memory location, leading to unexpected behavior or program crashes.

## 3. External Fragmentation
External fragmentation is a memory management issue that occurs when using dynamic memory allocation (DMA) in C++. It arises when there's sufficient free memory available in total to satisfy a memory allocation request, but the free memory is scattered across multiple non-contiguous blocks. These fragmented blocks are unusable because programs typically require contiguous memory to store data structures.

Even though there's enough total free space to fit a new box (memory allocation request), it might not fit in any of the existing free spaces because they're not contiguous.
This can lead to situations where your program has to request more memory from the operating system even though there's technically "free" memory available.

### Problems due to external fragmentation
* **Reduced Memory Efficiency**: The program might request more memory from the operating system even though there's technically free memory available.
* **Performance Degradation**: Frequent memory allocation requests can lead to performance overhead.
* **Program Crashes**: In severe cases, external fragmentation can make it impossible to allocate memory even when there's seemingly enough free memory, causing program crashes.


Binary file added static/img/day-12/Introduction.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added static/img/day-12/dmaInCpp.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added static/img/day-12/problems.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit b4da883

Please sign in to comment.