Manual memory management

Last updated

In computer science, manual memory management refers to the usage of manual instructions by the programmer to identify and deallocate unused objects, or garbage. Up until the mid-1990s, the majority of programming languages used in industry supported manual memory management, though garbage collection has existed since 1959, when it was introduced with Lisp. Today, however, languages with garbage collection such as Java are increasingly popular and the languages Objective-C and Swift provide similar functionality through Automatic Reference Counting. The main manually managed languages still in widespread use today are C and C++ – see C dynamic memory allocation.

Contents

Description

Many programming languages use manual techniques to determine when to allocate a new object from the free store. C uses the malloc function; C++ and Java use the new operator; and many other languages (such as Python) allocate all objects from the free store. Determining when an object ought to be created (object creation) is generally trivial and unproblematic, though techniques such as object pools mean an object may be created before immediate use. The real challenge is object destruction – determination of when an object is no longer needed (i.e. is garbage), and arranging for its underlying storage to be returned to the free store for re-use. In manual memory allocation, this is also specified manually by the programmer; via functions such as free() in C, or the delete operator in C++ – this contrasts with automatic destruction of objects held in automatic image de la société variables, notably (non-static) local variables of functions, which are destroyed at the end of their scope in C and C++.

Manual memory management techniques

For example


Manual management and correctness

Manual memory management is known to enable several major classes of bugs into a program when used incorrectly, notably violations of memory safety or memory leaks. These are a significant source of security bugs.

Languages which exclusively use garbage collection are known to avoid the last two classes of defects. Memory leaks can still occur (and bounded leaks frequently occur with generational or conservative garbage collection), but are generally less severe than memory leaks in manual systems.

Resource Acquisition Is Initialization

Manual memory management has one correctness advantage, which is that it allows automatic resource management via the Resource Acquisition Is Initialization (RAII) paradigm.

This arises when objects own scarce system resources (like graphics resources, file handles, or database connections) which must be relinquished when an object is destroyed – when the lifetime of the resource ownership should be tied to the lifetime of the object. Languages with manual management can arrange this by acquiring the resource during object initialization (in the constructor), and releasing during object destruction (in the destructor), which occurs at a precise time. This is known as Resource Acquisition Is Initialization.

This can also be used with deterministic reference counting. In C++, this ability is put to further use to automate memory deallocation within an otherwise-manual framework, use of the shared_ptr template in the language's standard library to perform memory management is a common paradigm. shared_ptr is not suitable for all object usage patterns, however.

This approach is not usable in most garbage collected languages – notably tracing garbage collectors or more advanced reference counting – due to finalization being non-deterministic, and sometimes not occurring at all. That is, it is difficult to define (or determine) when or if a finalizer method might be called; this is commonly known as the finalizer problem. Java and other GC'd languages frequently use manual management for scarce system resources besides memory via the dispose pattern: any object which manages resources is expected to implement the dispose() method, which releases any such resources and marks the object as inactive. Programmers are expected to invoke dispose() manually as appropriate to prevent "leaking" of scarce graphics resources. Depending on the finalize() method (how Java implements finalizers) to release graphics resources is widely viewed as poor programming practice among Java programmers, and similarly the analogous __del__() method in Python cannot be relied on for releasing resources. For stack resources (resources acquired and released within a single block of code), this can be automated by various language constructs, such as Python's with, C#'s using or Java's try-with-resources.

Performance

Many advocates of manual memory management argue that it affords superior performance when compared to automatic techniques such as garbage collection. Traditionally latency was the biggest advantage, but this is no longer the case. Manual allocation frequently has superior locality of reference.[ citation needed ]

Manual allocation is also known to be more appropriate for systems where memory is a scarce resource, due to faster reclamation. Memory systems can and do frequently "thrash" as the size of a program's working set approaches the size of available memory; unused objects in a garbage-collected system remain in an unreclaimed state for longer than in manually managed systems, because they are not immediately reclaimed, increasing the effective working set size.

Manual management has a number of documented performance disadvantages:

Latency is a debated point that has changed over time, with early garbage collectors and simple implementations performing very poorly compared to manual memory management, but sophisticated modern garbage collectors often performing as well or better than manual memory management.

Manual allocation does not suffer from the long "pause" times that occur in simple stop-the-world garbage collection, although modern garbage collectors have collection cycles which are often not noticeable.[ citation needed ]

Manual memory management and garbage collection both suffer from potentially unbounded deallocation times – manual memory management because deallocating a single object may require deallocating its members, and recursively its members' members, etc., while garbage collection may have long collection cycles. This is especially an issue in real time systems, where unbounded collection cycles are generally unacceptable; real-time garbage collection is possible by pausing the garbage collector, while real-time manual memory management requires avoiding large deallocations, or manually pausing deallocation.

Related Research Articles

<span class="mw-page-title-main">Garbage collection (computer science)</span> Form of automatic memory management

In computer science, garbage collection (GC) is a form of automatic memory management. The garbage collector attempts to reclaim memory which was allocated by the program, but is no longer referenced; such memory is called garbage. Garbage collection was invented by American computer scientist John McCarthy around 1959 to simplify manual memory management in Lisp.

In computer science, a memory leak is a type of resource leak that occurs when a computer program incorrectly manages memory allocations in a way that memory which is no longer needed is not released. A memory leak may also happen when an object is stored in memory but cannot be accessed by the running code. A memory leak has symptoms similar to a number of other problems and generally can only be diagnosed by a programmer with access to the program's source code.

In computer science, reference counting is a programming technique of storing the number of references, pointers, or handles to a resource, such as an object, a block of memory, disk space, and others.

Java and C++ are two prominent object-oriented programming languages. By many language popularity metrics, the two languages have dominated object-oriented and high-performance software development for much of the 21st century, and are often directly compared and contrasted. Java's syntax was based on C/C++.

<span class="mw-page-title-main">Memory management</span> Computer memory management methodology

Memory management is a form of resource management applied to computer memory. The essential requirement of memory management is to provide ways to dynamically allocate portions of memory to programs at their request, and free it for reuse when no longer needed. This is critical to any advanced computer system where more than a single process might be underway at any time.

In computer programming, a weak reference is a reference that does not protect the referenced object from collection by a garbage collector, unlike a strong reference. An object referenced only by weak references – meaning "every chain of references that reaches the object includes at least one weak reference as a link" – is considered weakly reachable, and can be treated as unreachable and so may be collected at any time. Some garbage-collected languages feature or support various levels of weak references, such as C#, Java, Lisp, OCaml, Perl, Python and PHP since the version 7.4.

In object-oriented programming (OOP), the object lifetime of an object is the time between an object's creation and its destruction. Rules for object lifetime vary significantly between languages, in some cases between implementations of a given language, and lifetime of a particular object may vary from one run of the program to another.

In computer science, a smart pointer is an abstract data type that simulates a pointer while providing added features, such as automatic memory management or bounds checking. Such features are intended to reduce bugs caused by the misuse of pointers, while retaining efficiency. Smart pointers typically keep track of the memory they point to, and may also be used to manage other resources, such as network connections and file handles. Smart pointers were first popularized in the programming language C++ during the first half of the 1990s as rebuttal to criticisms of C++'s lack of automatic garbage collection.

C dynamic memory allocation refers to performing manual memory management for dynamic memory allocation in the C programming language via a group of functions in the C standard library, namely malloc, realloc, calloc, aligned_alloc and free.

Resource acquisition is initialization (RAII) is a programming idiom used in several object-oriented, statically typed programming languages to describe a particular language behavior. In RAII, holding a resource is a class invariant, and is tied to object lifetime. Resource allocation is done during object creation, by the constructor, while resource deallocation (release) is done during object destruction, by the destructor. In other words, resource acquisition must succeed for initialization to succeed. Thus the resource is guaranteed to be held between when initialization finishes and finalization starts, and to be held only when the object is alive. Thus if there are no object leaks, there are no resource leaks.

<span class="mw-page-title-main">Dangling pointer</span> Pointer that does not point to a valid object

Dangling pointers and wild pointers in computer programming are pointers that do not point to a valid object of the appropriate type. These are special cases of memory safety violations. More generally, dangling references and wild references are references that do not resolve to a valid destination.

In computer science, a finalizer or finalize method is a special method that performs finalization, generally some form of cleanup. A finalizer is executed during object destruction, prior to the object being deallocated, and is complementary to an initializer, which is executed during object creation, following allocation. Finalizers are strongly discouraged by some, due to difficulty in proper use and the complexity they add, and alternatives are suggested instead, mainly the dispose pattern.

The Boehm–Demers–Weiser garbage collector, often simply known as Boehm GC, is a conservative garbage collector for C and C++ developed by Hans Boehm, Alan Demers, and Mark Weiser.

In the C++ programming language, new and delete are a pair of language constructs that perform dynamic memory allocation, object construction and object destruction.

In computer programming, unreachable memory is a block of dynamically allocated memory where the program that allocated the memory no longer has any reachable pointer that refers to it. Similarly, an unreachable object is a dynamically allocated object that has no reachable reference to it. Informally, unreachable memory is dynamic memory that the program cannot reach directly, nor get to by starting at an object it can reach directly, and then following a chain of pointer references.

In computer science, garbage includes data, objects, or other regions of the memory of a computer system, which will not be used in any future computation by the system, or by a program running on it. Because every computer system has a finite amount of memory, and most software produces garbage, it is frequently necessary to deallocate memory that is occupied by garbage and return it to the heap, or memory pool, for reuse.

In object-oriented programming, the dispose pattern is a design pattern for resource management. In this pattern, a resource is held by an object, and released by calling a conventional method – usually called close, dispose, free, release depending on the language – which releases any resources the object is holding onto. Many programming languages offer language constructs to avoid having to call the dispose method explicitly in common situations.

Memory safety is the state of being protected from various software bugs and security vulnerabilities when dealing with memory access, such as buffer overflows and dangling pointers. For example, Java is said to be memory-safe because its runtime error detection checks array bounds and pointer dereferences. In contrast, C and C++ allow arbitrary pointer arithmetic with pointers implemented as direct memory addresses with no provision for bounds checking, and thus are potentially memory-unsafe.

In computer science, region-based memory management is a type of memory management in which each allocated object is assigned to a region. A region, also called a zone, arena, area, or memory context, is a collection of allocated objects that can be efficiently reallocated or deallocated all at once. Like stack allocation, regions facilitate allocation and deallocation of memory with low overhead; but they are more flexible, allowing objects to live longer than the stack frame in which they were allocated. In typical implementations, all objects in a region are allocated in a single contiguous range of memory addresses, similarly to how stack frames are typically allocated.

In computer programming, resource management refers to techniques for managing resources.

References

See also