Variable-length stack allocated arrays

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Mon Jan 11 22:11:19 PST 2010


Chad J wrote:
> dsimcha wrote:
>> The optional buffer idiom is great for stuff that's returned from a function.  I
>> use it all the time.  On the other hand, for temporary buffers that are used
>> internally, whose mere existence is an implementation detail, having the caller
>> maintain and pass in a buffer is a horrible violation of encapsulation and good
>> API design, even by the standards of performance-oriented APIs.  Even if you know
>> it's never going to change, it's still annoying for the caller to even have to
>> think about these kinds of details.
>>
> 
> Yes, quite.

I think an API that is memory-safe relies on one global array like this:

template SuperStack(T) {
     private T[] buffer;
     private enum slackfactor = 2.5;

     T[] getBuffer(size_t n) {
         buffer.length = buffer.length + n;
         return buffer[$ - n .. $];
     }

     void releaseBuffer(T[] b) {
         enforce(b is buffer[$ - b.length .. $]);
         buffer.length = buffer.length - b.length;
         if (gc.capacity(buffer) > buffer.length * slackfactor) {
             // Reallocate buffer to allow collection of slack
             buffer = buffer.dup;
         }
     }
}

Further encapsulation is possible e.g. by defining a struct that pairs 
calls to getBuffer and releaseBuffer.

The idea is that the API offers a means to define and use temporary 
buffers without compromising memory safety. Even if you escape data 
allocated via getBuffer that persists after releaseBuffer, that will not 
cause undefined behavior. (It may, however, cause data to be overwritten 
because another call to getBuffer will reuse memory.) Leaks are also 
possible if you don't release the buffer. That can be solved by not 
offering getBuffer and releaseBuffer as they are, but instead only 
encapsulated in a struct with the appropriate constructor and destructor.


Andrei



More information about the Digitalmars-d mailing list