CO Lab Manual
Course Page
  • Course Information
    • Welcome
    • Introduction
    • Your Contributions
    • Lab Sessions and Etiquette
    • Team Setup
    • Assumed Prior Knowledge
  • Setup Guides
    • GitHub Repository Setup
    • Technical Setup
      • Windows
      • Linux
      • macOS
    • GitHub SSH Setup
    • Framework Setup
  • Reference Documentation
    • Introduction to the Documentation
    • A Brief History Lesson
    • Syntax (Intel vs. AT&T)
      • Section Exercises
    • Memory
      • Memory Management
      • Section Exercises
    • Registers
      • Section Exercises
    • Instructions
    • Subroutines
      • Calling Subroutines
      • Writing Subroutines
      • Section Exercises
    • Input/Output
      • Printing to the Terminal
      • Reading from the Terminal
      • Section Exercises
    • Programming Constructs
    • Assembler Directives
    • C/C++ vs Assembly
    • Building and Running Programs
    • Address Sanitization
    • A0: A Running Example
  • Assignments
    • Introduction to the Assignments
    • Mandatory Assignments
      • A1: Subroutines and I/O
      • A2: Recursion
    • Extra Assignments
      • A3-a: Fibonacci Calculator
      • A3-b: Fibonacci REPL
      • A4: Diff
      • A5: Printf
      • A6: HPC
      • A7: Bitmap
      • A8: Game
  • Appendix
    • Acknowledgments
    • Rules and Regulations
    • Frequently Asked Questions
    • How to use a Debugger
Powered by GitBook
On this page
  1. Reference Documentation
  2. Memory

Memory Management

This section introduces basic memory management functions which will prove useful in solving the extra assignments.

What does it do?

  • Dynamically allocates memory of a certain size on the heap. The allocated memory is uninitialized.

  • Linux man page: man malloc.

Signature

void *malloc(size_t size);
  • The first argument (size) represents the size of the memory segment to allocate, in bytes.

Analogy

Imagine you are a librarian; you have just received a packet of a known number of books and you have available a number of shelves in your library. You need to find an empty space on a shelf where you can store all your books. The books are new and more resistant to dust particles, so you do not need a clean shelf. Once you find such an empty space, place the books there. If no space was found, then you donate them.

Similarly, you give malloc a certain size that you need for your program (the number of books) and malloc will try to find in your memory a segment (empty space on a shelf) big enough to fit the requested size. If it finds one, malloc will return a pointer to the start address of the allocated memory (in the library example this would be the shelf number) which you can use to access that memory block. If it does not find one, malloc will return NULL (the packet was not placed on a shelf).

What does it do?

  • Resizes a block in the memory that was previously allocated with malloc, calloc, or realloc.

  • Linux man page: man realloc.

Signature

void *realloc(void *ptr, size_t new_size);
  • The first argument (ptr) represents a pointer to a memory segment, which was allocated with malloc, realloc, or calloc.

  • The second argument (new_size) represents the new size of the memory segment to which ptr points to.

Analogy

Imagine you want to celebrate your performance in the ''Computer Organization 2024-2025'' course, so you book a table at a restaurant for nnn people. More of your friends decide to join, so you need to call the restaurant to change your reservation from nnn people to mmm people (m≥n)(m \ge n)(m≥n), in order for all your friends to sit together at the same table.

Similarly, you previously allocated a memory block of a certain size with malloc and you have a pointer ptr returned by the malloc call. At some point in time you decide that you need a bigger memory block, so you decide to use realloc to resize it. realloc will take as parameters your pointer ptr and the new size and will try to find in the memory of your computer a new memory block big enough. Once it finds such a block, realloc will move the content of the previous memory block to the new memory block and it frees the previous memory block. At the end, it will return a new pointer ptr that will indicate the start address of the new memory block. If realloc does not find such a block, it will return NULL.

Note: realloc may return the same pointer if the current memory block could be extended in-place (similarly to putting two tables together). Additionally, realloc can also shrink memory blocks if the parameter new_size is smaller than the originally allocated size.

What does it do?

  • Allocates initialized memory blocks for a number of objects of a certain size. The memory blocks will be initialized with 0.

  • Linux man page: man calloc.

Signature

void *calloc(size_t num, size_t size);
  • The first argument (num) represents the array size (number of objects).

  • The second argument (size) represents the size of each object of the array.

Analogy

Imagine that you buy a number of limited edition books of the same size. By knowing the number of books, you need to find a space on a shelf that is big enough so that all the books fit. When you find such a space, you will clean the space of dust and you will place the books there.

Similarly, calloc will receive a number of n objects of a certain size m and will try to find n contiguous memory blocks of size m to allocate for those objects. When it finds them, calloc will initialize all blocks with 0 and then it will return a pointer that points to the address of the first object. If calloc does not find enough available space for all objects, then it will return NULL.

Similarity with malloc

Now you may be wondering how malloc and calloc do the same thing, except the initialization part. Well, think about a block of size k as a number of n blocks of size m such that k = n x m. Consider k to be a block of 64 bits, n to be 8, and m a block of 8 bits. Then when you make a malloc call (depending on the purpose of the memory allocation) you can write it as:

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

or as:

int8_t *ptr = (int8_t*)malloc(8 * sizeof(int8_t));

The later malloc call looks similar to a calloc call in which you provide as arguments n as the number of objects and m as the size of an object. Such a call could look like:

int8_t *ptr = (int8_t*)calloc(8, sizeof(int8_t));

As a result, malloc and calloc have similar functionality. Very important to remember is the fact that calloc initializes the allocated memory blocks with 0, while malloc does not.

What does it do?

  • Deallocates a memory block that was previously allocated by calling malloc, calloc or realloc.

  • Linux man page: man free.

Signature

void free(void *ptr);
  • The first argument (ptr) represents a pointer to a memory segment that was allocated with malloc, realloc, and calloc.

Analogy

Imagine that you allocated some space on a shelf for a certain number of books and you decided to donate them. Once you remove the books from the shelf, the shelf is no longer assigned to those books, so you can store new books on it.

Similarly, when you decide that a previously allocated memory block is no longer needed, by calling free, you mark that memory block as "not in use" and, in the future, you will be able to make new memory allocations on that memory region (the new memory allocation does not have to be of the same size as the old one).

You should always free the memory allocations not use anymore to avoid memory leaks.

PreviousMemoryNextSection Exercises

Last updated 4 months ago