Memory Management
Most non-trivial programs needs to allocate and free memory. Memory management techniques become more and more important as programs increase in complexity, size, and performance. D offers many options for managing memory.
The three primary methods for allocating memory in D are:
- Static data, allocated in the default data segment.
- Stack data, allocated on the CPU program stack.
- Garbage collected data, allocated dynamically on the garbage collection heap.
The techniques for using them, as well as some advanced alternatives are:
- Strings (and Array) Copy-on-Write
- Real Time
- Smooth Operation
- Free Lists
- Reference Counting
- Explicit Class Instance Allocation
- Mark/Release
- RAII (Resource Acquisition Is Initialization)
- Allocating Class Instances On The Stack
- Allocating Uninitialized Arrays On The Stack
- Interrupt Service Routines
Strings (and Array) Copy-on-Write
Consider the case of passing an array to a function, possibly modifying the contents of the array, and returning the modified array. As the contents of an array are accessed through a reference, a crucial issue is who owns the contents of the array? For example, a function to convert an array of characters to upper case:
char[] toupper(char[] s)
{
int i;
for (i = 0; i < s.length; i++)
{
char c = s[i];
if ('a' <= c && c <= 'z')
s[i] = cast(char)(c - ('a' - 'A'));
}
return s;
}
Note that the caller's version of s[] is also modified. This may be not at all what was intended, or worse, s[] may be a slice into a read-only section of memory.
If a copy of s[] was always made by toupper(), then that will unnecessarily consume time and memory for strings that are already all upper case.
The solution is to implement copy-on-write, which means that a copy is made only if the string needs to be modified. Some string processing languages do do this as the default behavior, but there is a huge cost to it. The string "abcdeF" will wind up being copied 5 times by the function. To get the maximum efficiency using the protocol, it'll have to be done explicitly in the code. Here's toupper() rewritten to implement copy-on-write in an efficient manner:
char[] toupper(char[] s)
{
int changed;
int i;
changed = 0;
for (i = 0; i < s.length; i++)
{
char c = s[i];
if ('a' <= c && c <= 'z')
{
if (!changed)
{
char[] r = new char[s.length];
r[] = s;
s = r;
changed = 1;
}
s[i] = cast(char)(c - ('a' - 'A'));
}
}
return s;
}
Copy-on-write is the protocol implemented by array processing functions in the D Phobos runtime library.