This is an old revision of the document!


Lab03: Memory Safety

During this lab you will learn about the memory safety mechanisms that are available in D.

@safe functions

A class of programming errors involve corrupting data at unrelated locations in memory by writing at those locations unintentionally. Such errors are mostly due to mistakes made in using pointers and applying type casts. @safe functions guarantee that they do not contain any operation that may corrupt memory. An extensive list of operations that are forbidden in @safe functions can be found here.

Let's take this code for example:

import std.stdio : writeln;
 
void main()                                                                                                                                   
{
    int a = 7;
    int b = 9;
 
    /* some code later */
 
    *(&a + 1) = 2;
    writeln(b);
    writeln(b);
}

Running this code yields the result:

9
2

Wait, what? No, this is not a typo: the value of b changes between two instructions for no apparent reason. This is happening because the compiler does not offer any guarantees when it comes to pointer arithmetic on local variables; so by definition this is an unsafe operation and if faulting line would have been hidden between another 1K lines of code, it would have taken a lot of time to get to the root of the problem. Now let us annotate the main function definition with @safe:

void main() @safe

The compiler correctly highlights:

test.d(10): Error: cannot take address of local a in @safe function main

@trusted

The safety rules work well to prevent memory corruption, but they prevent a lot of valid, and actually safe, code. For example, consider a function that wants to use the system call read, which is prototyped like this:

ssize_t read(int fd, void* ptr, size_t nBytes);

For those unfamiliar with this function, it reads data from the given file descriptor, and puts it into the buffer pointed at by ptr and expected to be nBytes bytes long. It returns the number of bytes actually read, or a negative value if an error occurs.

Using this function to read data into a stack-allocated buffer might look like this:

ubyte[128] buf;
auto nread = read(fd, buf.ptr, buf.length);

How is this done inside a @safe function? The main issue with using read in @safe code is that pointers can only pass a single value, in this case a single ubyte. read expects to store more bytes of the buffer. In D, we would normally pass the data to be read as a dynamic array. However, read is not D code, and uses a common C idiom of passing the buffer and length separately, so it cannot be marked @safe. Consider the following call from @safe code:

auto nread = read(fd, buf.ptr, 10_000);

This call is definitely not safe. What is safe in the above read example is only the one call, where the understanding of the read function and calling context assures memory outside the buffer will not be written.

To solve this situation, D provides the @trusted attribute, which tells the compiler that the code inside the function is assumed to be @safe, but will not be mechanically checked. It’s on you, the developer, to make sure the code is actually @safe.

A function that solves the problem might look like this in D:

auto safeRead(int fd, ubyte[] buf) @trusted
{
    return read(fd, buf.ptr, buf.length);
}

Whenever marking an entire function @trusted, consider if code could call this function from any context that would compromise memory safety. If so, this function should not be marked @trusted under any circumstances. Even if the intention is to only call it in safe ways, the compiler will not prevent unsafe usage by others. safeRead should be fine to call from any @safe context, so it’s a great candidate to mark @trusted.

@system

@system is the default safety attribute for functions and it implies that no automatic safety checks are performed.

dss/laboratoare/03.1560424629.txt.gz · Last modified: 2019/06/13 14:17 by razvan.nitu1305
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0