Skip to content

Dyrun/cpp-memory-dynamic

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 

Repository files navigation

Memory management workshop

Foundations of memory allocation and deallocation

When you dynamically allocate memory using the new operator in C++, it triggers a complex process involving interaction between the operating system and your program.

Steps Involved:

  • User Request: During program execution, a point is reached where additional memory is required. The new operator is used to specify the amount of memory to be allocated.
  • System Call: Invoking the new operator results in a system call being made to the operating system. Essentially, this system call is a request to the operating system to provide a free memory block of a specified size for the program.
  • Searching for Free Memory: The operating system searches for available memory blocks. Free memory is typically managed as a contiguous block, but due to allocations and deallocations during program execution, it may become fragmented. The operating system must find a free block large enough to satisfy the requested size.
  • Memory Allocation and Address Return: If a suitable free block is found, the operating system allocates this portion and returns a memory address to the program. This address is the location where the program can read from and write to within the newly allocated memory.
  • Updating Memory Management Tables: The operating system updates its internal memory management tables to reflect that the allocated memory is no longer free.
  • Returning a Pointer: The system call returns to the program, passing the returned memory address as a pointer. The program can use this pointer to access the allocated memory.

How does the heap work in practice? The heap, a dynamically allocated memory region, is distinct from the fixed-size sections created at compile time. While the heap can grow to accommodate new allocations, the boundaries of the pre-allocated sections remain unchanged. This separation ensures that dynamic memory allocation does not interfere with the program's code or static data. The heap is also capable of shrinking.

How does the stack work in practice? Stack memory is allocated at the beginning of program execution and maintains a fixed size and cannot be arbitrarily increased. Attempting to exceed the stack's capacity results in a stack overflow.

Allocating memory with the new operator does not ensure a contiguous memory block. Several factors contribute to the ability to treat allocated memory as a contiguous block, even if it's not physically contiguous:

  • Abstraction:C++ (and other high-level languages) hides the complexities of memory management. When you allocate memory using new, you receive a logical memory address. This address represents the beginning of a contiguous block of memory from your program's perspective, regardless of how the memory is physically fragmented.
    Pointer arithmetic reinforces this logical view. As you iterate through an array using a pointer, the language ensures that the pointer always points to the next element, even if the underlying physical memory is non-contiguous.
  • Allocators: The new operator typically invokes an allocator behind the scenes. Allocators are responsible for managing memory allocation and deallocation. Modern allocators are often sophisticated enough to find the largest contiguous blocks of memory possible for allocation. Even if the physical memory is fragmented, the allocator attempts to hide this fragmentation from the program.

What happens if you try to access a memory location that has not been reserved for your program? The operating system protects memory by ensuring that each program has its own designated memory space. If a program tries to access memory that it's not supposed to, the OS will usually stop the program. This is done through mechanisms like memory protection and page faults. The hardware also plays a role, with the MMU preventing programs from accessing invalid memory addresses.

The concept and consequences of memory leaks

A memory leak occurs when a program reserves a specific amount of memory but doesn't free it before the program ends. This is a frequent programming error that can be difficult to identify.
Upon program termination, the operating system ends the corresponding process. Consequently, all resources consumed by the program, such as memory, are supposed to be freed.

Assignments

Preparations

To make our jobs easier and avoid tool-related issues, let's use a common environment where everything is already set up. Here's how to do it.
Within the .devcontainer folder, you'll find a file that describes a C++ development environment. By utilizing this file in Visual Studio Code, you can establish a connection to a Linux-based development environment. The steps involved are as follows:

  • Make sure you have Docker Desktop installed and running on your computer.
  • Install the Remote Development extension pack in Visual Studio Code. Once the installations are complete, follow these steps:
  • Open the Command Palette (usually by pressing Ctrl+Shift+P) and search for Dev Containers: Clone Repository in Container Volume
  • You may need to authorize the extension for GitHub authentication. You will be redirected to your web browser to complete this process.
  • A development container will be created and started in the background. You may see a terminal window open while the container is being created.

Assignment: Detecting and Fixing Memory Leaks

The source file for the next task is located in the ./dynamic_memory directory.
Hint: you may find the following instructions useful for completing this task:

  • compile the project:
g++ ./main.cpp ./Logger.cpp -o main
  • run a memory checker:
valgrind --leak-check=full ./main

Check the program

Analyze the program's architecture and behavior. Determine if there is a memory leak present.

Freeing Allocated Memory

Resolve the memory leak by deallocating the memory that is no longer being used!

Replacing Raw Pointers with Smart Pointers

Fix the leak by using smart pointers!

Memory Management without Pointers

Resolve the memory leak by minimizing or eliminating the use of pointers.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors