This Week in D March 12, 2017

Welcome to This Week in D! Each week, we'll summarize what's been going on in the D community and write brief advice columns to help you get the most out of the D Programming Language.

The D Programming Language is a general purpose programming language that offers modern convenience, modeling power, and native efficiency with a familiar C-style syntax.

This Week in D has an RSS feed.

This Week in D is edited by Adam D. Ruppe. Contact me with any questions, comments, or contributions.

Statistics

In the community

Community announcements

See more at the announce forum.

Tip of the Week

Today's tip is from ketmar about avoiding false positives on the 32 bit GC implementation.

It is often handy to have a list of something in your data types. Like list of strings, or some structs. And you may need to access any list item by index, fast. The obvious choice for that is dynamic array.

 int[] lineOffsets;

Yet if your array grows big enough, it becomes a target for "false positives" in GC: GC sees some number on stack or in another memory area, interprets it as a pointer, and that "false pointer" happens to point somewhere inside lineOffsets. Thus, while your object may be collected by GC, "false positive" prevents collecting the array, and your program starts leaking memory.

Now, D GC has a nice set of flags for allocated memory blocks, including "ignore interior pointers" (i.e. ignore all ponters that points somewhere inside the block). If our array is private member, and we have nice getters and setters for it, it is guaranteed that lineOffsets is the only "root", so it is safe to mark the array with that flag. The following code appends elements to array and sets the flag (if it is safe):

 void appendLineOffset (int newofs) {
   auto optr = lineOffsets.ptr;
   lineOffsets ~= newofs;
   // check if runtime allocated a new memory block due to array growth
   if (lineOffsets.ptr !is optr) {
     import core.memory : GC;
     // check if our array really *IS* the head
     if (lineOffsets.ptr is GC.addrOf(lineOffsets.ptr)) {
       // set the magic flag!
       GC.setAttr(lineOffsets.ptr, GC.BlkAttr.NO_INTERIOR);
     }
   }
 }

By using this code instead of simply lineOffsets ~= newofs;, i reduced memory leaks in some my projects to none.

Please note that if you're using slices of lineOffsets, they must NOT outlive the array itself, because with "no interior" flag slices cannot "anchor" array anymore, if they're not starting at [0] element. I.e. the only really safe mode is to not allow "outside code" to get slices of lineOffsets in any way.

Learn more about D

To learn more about D and what's happening in D: