Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Memory Allocation/Deallocation? [closed]

I have been looking at memory allocation lately and I am a bit confused about the basics. I haven't been able to wrap my head around the simple stuff. What does it mean to allocate memory? What happens? I would appreciated answers to any of these questions:

  1. Where is the "memory" that is being allocated?
  2. What is this "memory"? Space in an array? Or something else?
  3. What happens exactly when this "memory" gets allocated?
  4. What happens exactly when the memory gets deallocated?
  5. It would also really help me if someone could answer what malloc does in these C++ lines:

    char* x;  x = (char*) malloc (8); 

Thank you.

like image 715
Isaac Avatar asked Mar 24 '13 21:03

Isaac


People also ask

What is deallocation of memory?

Deallocation of memory by the Operating System (OS) is a way to free the Random Access Memory (RAM) of finished processes and allocate new ones.

What are memory allocation and deallocation functions?

Memory allocation is accomplished using the new operator and deallocation is accomplished using the delete operator. When a program requires a variable, it uses new to allocate the variable. When the program no longer needs the variable, it uses delete to deallocate it.

What is memory allocation and deallocation in data structure?

Memory allocation is the process of setting aside sections of memory in a program to be used to store variables, and instances of structures and classes. There are two types of memory allocations possible in C: Compile-time or Static allocation. Run-time or Dynamic allocation (using pointers).

What is deallocation of memory in C++?

In C++ when we want to allocate memory from the free-store (or we may call it heap) we use the new operator. int *ptr = new int; and to deallocate we use the delete operator.


2 Answers

The Memory Model

The C++ standard has a memory model. It attempts to model the memory in a computer system in a generic way. The standard defines that a byte is a storage unit in the memory model and that memory is made up of bytes (§1.7):

The fundamental storage unit in the C++ memory model is the byte. [...] The memory available to a C++ program consists of one or more sequences of contiguous bytes.

The Object Model

The standard always provides an object model. This specifies that an object is a region of storage (so it is made up of bytes and resides in memory) (§1.8):

The constructs in a C++ program create, destroy, refer to, access, and manipulate objects. An object is a region of storage.

So there we go. Memory is where objects are stored. To store an object in memory, the required region of storage must be allocated.

Allocation and Deallocation Functions

The standard provides two implicitly declared global scope allocation functions:

void* operator new(std::size_t); void* operator new[](std::size_t); 

How these are implemented is not the standard's concern. All that matters is that they should return a pointer to some region of storage with the number of bytes corresponding to the argument passed (§3.7.4.1):

The allocation function attempts to allocate the requested amount of storage. If it is successful, it shall return the address of the start of a block of storage whose length in bytes shall be at least as large as the requested size. There are no constraints on the contents of the allocated storage on return from the allocation function.

It also defines two corresponding deallocation functions:

void operator delete(void*); void operator delete[](void*); 

Which are defined to deallocate storage that has previously been allocated (§3.7.4.2):

If the argument given to a deallocation function in the standard library is a pointer that is not the null pointer value (4.10), the deallocation function shall deallocate the storage referenced by the pointer, rendering invalid all pointers referring to any part of the deallocated storage.

new and delete

Typically, you should not need to use the allocation and deallocation functions directly because they only give you uninitialised memory. Instead, in C++ you should be using new and delete to dynamically allocate objects. A new-expression obtains storage for the requested type by using one of the above allocation functions and then initialises that object in some way. For example new int() will allocate space for an int object and then initialise it to 0. See §5.3.4:

A new-expression obtains storage for the object by calling an allocation function (3.7.4.1).

[...]

A new-expression that creates an object of type T initializes that object [...]

In the opposite direction, delete will call the destructor of an object (if any) and then deallocate the storage (§5.3.5):

If the value of the operand of the delete-expression is not a null pointer value, the delete-expression will invoke the destructor (if any) for the object or the elements of the array being deleted.

[...]

If the value of the operand of the delete-expression is not a null pointer value, the delete-expression will call a deallocation function (3.7.4.2).

Other Allocations

However, these are not the only ways that storage is allocated or deallocated. Many constructs of the language implicitly require allocation of storage. For example, giving an object definition, like int a;, also requires storage (§7):

A definition causes the appropriate amount of storage to be reserved and any appropriate initialization (8.5) to be done.

C standard library: malloc and free

In addition, the <cstdlib> header brings in the contents of the stdlib.h C standard library, which includes the malloc and free functions. They are also defined, by the C standard, to allocate and deallocate memory, much like the allocation and deallocation functions defined by the C++ standard. Here's the definition of malloc (C99 §7.20.3.3):

void *malloc(size_t size);
Description
The malloc function allocates space for an object whose size is specified by size and whose value is indeterminate.
Returns
The malloc function returns either a null pointer or a pointer to the allocated space.

And the definition of free (C99 §7.20.3.2):

void free(void *ptr);
Description
The free function causes the space pointed to by ptr to be deallocated, that is, made available for further allocation. If ptr is a null pointer, no action occurs. Otherwise, if the argument does not match a pointer earlier returned by the calloc, malloc, or realloc function, or if the space has been deallocated by a call to free or realloc, the behavior is undefined.

However, there's never a good excuse to be using malloc and free in C++. As described before, C++ has its own alternatives.


Answers to Questions

So to answer your questions directly:

  1. Where is the "memory" that is being allocated?

    The C++ standard doesn't care. It simply says that the program has some memory which is made up of bytes. This memory can be allocated.

  2. What is this "memory"? Space in an array? Or something else?

    As far as the standard is concerned, the memory is just a sequence of bytes. This is purposefully very generic, as the standard only tries to model typical computer systems. You can, for the most part, think of it as a model of the RAM of your computer.

  3. What happens exactly when this "memory" gets allocated?

    Allocating memory makes some region of storage available for use by the program. Objects are initialized in allocated memory. All you need to know is that you can allocate memory. The actual allocation of physical memory to your process tends to be done by the operating system.

  4. What happens exactly when the memory gets deallocated?

    Deallocating some previously allocated memory causes that memory to be unavailable to the program. It becomes deallocated storage.

  5. It would also really help me if someone could answer what malloc does in these C++ lines:

    char* x;  x = (char*) malloc (8); 

    Here, malloc is simply allocating 8 bytes of memory. The pointer it returns is being cast to a char* and stored in x.

like image 130
Joseph Mansfield Avatar answered Sep 28 '22 10:09

Joseph Mansfield


1) Where is the "memory" that is being allocated?

This is completely different based on your operating system, programming environment (gcc vs Visual C++ vs Borland C++ vs anything else), computer, available memory, etc. In general, memory is allocated from what is called the heap, region of memory just waiting around for you to use. It will generally use your available RAM. But there are always exceptions. For the most part, so long as it gives us memory, where it comes from isn't a great concern. There are special types of memory, such as virtual memory, which may or may not actually be in RAM at any given time and may get moved off to your hard drive (or similar storage device) if you run out of real memory. A full explanation would be very long!

2) What is this "memory"? Space in an array? Or something else?

Memory is generally the RAM in your computer. If it is helpful to think of memory as a gigantic "array", it certain operates like one, then think of it as a ton of bytes (8 bit values, much like unsigned char values). It starts at an index of 0 at the bottom of memory. Just like before, though, there are tons of exceptions here and some parts of memory may be mapped to hardware, or may not even exist at all!

3) What happens exactly when this "memory" gets allocated?

At any given time there should be (we really hope!) some of it available for software to allocate. How it gets allocated is highly system dependent. In general, a region of memory is allocated, the allocator marks it as used, and then a pointer is given to you to use that tells the program where in all of your system's memory that memory is located. In your example, the program will find a consecutive block of 8 bytes (char) and return a pointer to where it found that block after it marks it as "in use".

4) What happens exactly when the memory gets deallocated?

The system marks that memory as available for use again. This is incredibly complicated because this will often cause holes in memory. Allocate 8 bytes then 8 more bytes, then deallocate the first 8 bytes and you've got a hole. There are entire books written on handling deallocation, memory allocation, etc. So hopefully the short answer will be sufficient!

5) It would also really help me if someone could answer what malloc does in these C++ lines:

REALLY crudely, and assuming it's in a function (by the way, never do this because it doesn't deallocate your memory and causes a memory leak):

void mysample() {   char *x; // 1   x = (char *) malloc(8); // 2 } 

1) This is a pointer reserved in the local stack space. It has not be initialized so it points to whatever that bit of memory had in it.

2) It calls malloc with a parameter of 8. The cast just let's C/C++ know you intend for it to be a (char *) because it returns a (void *) meaning it has no type applied. Then the resulting pointer is stored in your x variable.

In very crude x86 32bit assembly, this will look vaguely like

PROC mysample:   ; char *x;   x = DWord Ptr [ebp - 4]   enter 4, 0   ; Enter and preserve 4 bytes for use with     ; x = (char *) malloc(8);   push 8       ; We're using 8 for Malloc   call malloc  ; Call malloc to do it's thing   sub esp, 4   ; Correct the stack   mov x, eax   ; Store the return value, which is in EAX, into x    leave   ret 

The actual allocation is vaguely described in point 3. Malloc usually just calls a system function for this that handles all the rest, and like everything else here, it's wildly different from OS to OS, system to system, etc.

like image 36
Mark Ormston Avatar answered Sep 28 '22 09:09

Mark Ormston