Read: Working with Memory

As previously stated, from a programmer’s perspective, memory is abstracted into variables. This hides most of the lower level abstractions. Each variable is characterized by an address (or location in memory), type and access rights. Some languages require that the developer spells out these attributes explicitly (statically typed languages - notable examples: C\C++, D, Java) whereas others deduce them by analyzing the context (dynamically typed languages - notable examples: Python, JavaScript). Nevertheless, the language compiler needs to handle this information and, based on it, generate code that manages memory correctly and efficiently.

Memory Access

Accessing memory is defined by reading or writing values to or from a variable. From a programmer’s perspective, this looks pretty straightforward:

int main(void)
{
	int a;               // declare variable
	a = 42;              // write 42 to variable a
	printf("%d\n", a);   // read variable a and print its contents

	return 0;
}

However, from a lower level perspective, there are other attributes that need to be taken care of. For instance, variable a needs to have a correspondent area that is reserved in memory. That specific chunk of memory is described by an address and a size. The address for a is automatically generated by going through multiple layers of abstractions, but the size is spelled out indirectly by the programmer by using the keyword int. Another aspect is represented by the access rights for a specific memory area. In our example, a is defined as being plain mutable, however, it is possible to declare constant variables which are stored in memory location with no writing rights.

Using the above information, the compiler and the operating system co-work to allocate memory that can represent the contents of the variable.

No matter what sort of language you are using, statically or dynamically typed, a variable is always described by the (address, size, access rights) triplet. By using this triplet, the content of a variable is stored, retrieved or rewritten.

Memory Protection

Memory contents (both code and data) are separated into sections or zones. This makes it easier to manage. More than that, it allows different zones to have different permissions. This follows the principle of least privilege where only required permissions are part of a given section.

Code is usually placed in a section (.text) with read and execute permissions; no write permissions. Variables are placed in different sections (.data, .bss, stack, heap) with read and write permissions; no execute permissions.