Memory corruption bugs are one of the most frustrating problems a C programmer can encounter. Memory corruption is writing to what you believed was memory owned by one object; it affects another object in unpredictable ways, leading to crashes. D aims to reduce the scope and occurrence of these bugs by providing a statically checked memory-safe subset which, ideally, exhibits no undefined behavior. In practice, @safe
isn't perfect due to bugs in the specification and the implementation, but it nevertheless helps to significantly reduce the probability of memory corruption bugs.
Perform the following steps by using @safe
:
@safe
annotation and try to compile. The compiler will tell you which functions failed the test.foreach
, references, and D array slices instead of low-level features such as pointers wherever possible.ptr++;
with slice = slice[1 .. $];
.cast
operator.@safe
functions must also be marked @safe
.@trusted
.@trusted
. The garbage collector will never free a reference prematurely.@safe
, mark functions @system
. These attributes work on the function level, so you may have to re-factor code into additional functions to reach the level of granularity you need.Consider the following code snippet:
@safe void foo() {}
The @safe
annotation (sometimes called SafeD because that was the first-draft name of the concept) is an opt-in set of restrictions that aim to make D code have no undefined behavior and be memory safe, ensuring that memory is never unexpectedly corrupted.
The @safe
annotation prohibits the use of several of D's lower-level features:
@safe
or @trusted
, since the compiler cannot verify whether they are implemented correctlyException
, since the Throwable
tree derived from Error
signify unrecoverable errors@safe
does not prevent null pointer dereferences. Since the program is terminated by a null pointer (through a segmentation fault or an unrecoverable Error being thrown), no memory corruption will occur. A crashing program might be annoying and may fail to release resources or leave a file half-written, but since the behavior of immediate termination is well-defined, it is not prevented by restrictions of @safe
. It is recommended that you use early-and-often assertions
and/or NotNull
types to aid in debugging null reference issues.
The recurring theme is that @safe
is about guarantees. If the compiler cannot guarantee it is correct, it is prohibited. What about the times when the compiler cannot make a guarantee, but the programmer can? This is where @trusted
comes into play.
The @trusted
functions violate one of the @safe
rules, but is manually verified to do it correctly; the compiler trusts you to get it right. For example, using pointer arithmetic is memory safe, if and only if kept within bounds. If you can manually verify this is done correctly, you may mark the function @trusted
. If you do, the function should be limited to returning a strongly-typed D slice (whose bounds are known to the D compiler and/or runtime and managed automatically), which is then worked with inside a fully @safe
function. A @trusted
function should be as small and as simple as possible.
It is a mistake to mark too many functions @trusted
. It is better to rewrite functions to use higher level features whenever possible. Pointer arithmetic can be translated into array slice operations: slice = slice[1 .. $]
generates the same code as ++ptr;
(although with range boundary checks inserted when the compiler cannot statically ensure the operation is in bounds). The slice[0] = 0;
statement generates the same code as *ptr = 0;
.
The --ptr;
value is a bit trickier to convert, since slice = slice[-1 .. $];
will generate an out-of-bounds error. To solve this problem, use two variables: a buffer slice and an index integer. Manipulate the integer instead of the slice or pointer.
The @system
functions have no restrictions. It is the default safety level because of D's heritage from C. If you want to ensure your entire program is memory-safe, you may mark main @safe
; though @safe
is opt-in, this may limit your usage of libraries.
@safe
, @system
, and @trusted
3.12.153.212