Memory management is a form of resource management, referring specifically to the management of computer memory, or RAM. The core of the issue is to manage the allocation system memory when its needed and its release when it is no longer required. In modern computers, memory management also involves managing the virtual addressing system for each running process. Depending on the programming language, memory management can be manual, automatic, or both.
What does memory management do?
Every computer has a limited supply of memory that has to be shared across all running processes. Memory management ensures that this limited resource is freed up when no longer needed. Many older languages, such as C focus on manual memory management. This means that the developer of the application has to specifically allocate resources for values that need to be stored in memory. Once these variables are no longer required, the developer also has to release the memory again.
One of the other factors of manual memory management is needing to initialise variables and clear data before releasing the memory. For example, if you allocate memory to a variable, a memory address is assigned. No further actions are taken, so this memory address may contain values from its previous use that were never cleared. Acting on the data in uninitialized memory can have unpredictable results, which can involve garbage responses and program crashes. Even if you try to put data in the memory, if you don’t fill the whole space allocated to the variable, the space you didn’t use can contain uninitialized data. To avoid this, it’s important to initialise variables when manually managing memory.
Tip: Initialising a variable is the process of setting a variable to a known starter value, typically clearing it.
More modern languages, such as Python, tend to use automatic memory management. This automatically runs all the initialisation, and garbage collection procedures in the background. This reduces the complexity of development, however, it can affect performance somewhat and gives slightly less direct control to the developer.
Issues with memory management
There are a few ways in which messing up memory management can cause potentially serious issues. Using uninitialised memory, for example, can lead to undefined behaviour. Conversely, not clearing memory before releasing it can potentially leak data to the next application that tries to use that section of memory.
Once a memory location is no longer needed, it should be released. This allows the computer to reassign it to other software as it’s needed. If you don’t clean up unnecessary memory after yourself, this is referred to as a memory leak. This isn’t necessarily a huge issue in short-running programs, as once the process ends, the memory will be released. But for long-running software, this can end up consuming more and more system memory, until the computer runs out, typically resulting in the software crashing.
It’s important to ensure that the data you’re storing in a variable fits within the memory allocated to that variable. If you have a variable designed to hold three characters and try to write twenty characters to it, this is a buffer overflow. Buffer overflows can affect adjacent memory addresses resulting in memory corruption.
Memory management issues result in unintended behaviour. This primarily takes the form of crashes or errors. In worst-case scenarios, however, it can result in code execution vulnerabilities. If the unintended behaviour is predictable, it may be possible to provide a specific input that results in the program executing malicious code. As such, good memory management is important in developing secure code.
One of the hidden factors of memory management is the use of virtual memory. Virtual memory is managed by the operating system rather than the application meaning developers can’t really affect it. Instead of being assigned actual physical memory addresses, each process is assigned its own unique memory address space. The operating system then converts the virtual address to a physical address whenever it needs to access memory.
One of the key advantages of using virtual memory is that it segments the memory address space between processes. This prevents one process from being able to read the memory of another. While generally not an issue for legitimate software, this helps to protect against malware and rogue software infecting or stealing data from other programs. It also helps to prevent buffer overflows from affecting different processes.
As an extra benefit, using virtual memory addresses allows the operating system to adjust the physical location of the data being stored as needed. This generally is used to transfer rarely used memory to a page or swap file on a storage drive when memory resources are strained. This incurs a hit to performance when those virtual memory addresses are needed, as storage is slower than true RAM, but it also prevents system or application crashes, which is generally preferred.
Memory management is the process of managing the limited resource of system RAM. In software, this is now generally performed automatically, however, some programming languages allow or require the manual management of memory. Mismanaging memory can lead to a large range of memory corruption issues and potentially to code execution vulnerabilities. The operating system also performs some memory management in the form of virtual addresses. This allows it to segregate the memory of each process, a useful security feature. It also allows the operating system to adjust the physical location of data without affecting the actual process.