D array expansion and non-deterministic re-allocation

Bartosz Milewski bartosz-nospam at relisoft.com
Tue Nov 24 14:35:43 PST 2009


Steven Schveighoffer Wrote:

> On Tue, 24 Nov 2009 16:52:52 -0500, Bartosz Milewski  
> <bartosz-nospam at relisoft.com> wrote:
> 
> > Steven Schveighoffer Wrote:
> >> > Imagine you're reviewing this code written by a relative newbee:
> >> >
> >> > char[] quote(char[] word) {
> >> >   word.length += 2;
> >> >   word[length-1] = '"';
> >> >   for(int i = word.length-2; i > 0; --i)
> >> >     word[i] = word[i - 1];
> >> >   word[0] = '"';
> >> >   return word;
> >> > }
> >> >
> >> > void storeFoos(char[] buffer, string pattern, Container c)
> >> > {
> >> > 	char[] res = find(buffer, pattern);
> >> > 	c.store(quote(res[0..pattern.len]);
> >> > }
> >> >
> >> > Is this buggy? If so, how and when will the bug manifest itself?
> >>
> >> In my mind it is not buggy.  If quote or storeFoos is not meant to be  
> >> able
> >> to molest the data, it should require a const(char)[].  If this was D1
> >> code, I'd say it depends on the purpose of storeFoos, if storeFoos is
> >> expecting to own the input buffer, it's not buggy.  If it's not, then
> >> storeFoos is buggy (in all cases).  But we aren't talking about D1.
> > Yes, a lot depends on what's expected of storeFoos. Suppose that the  
> > surrounding code expects the buffer not to be modified. The newbee  
> > didn't want to idup the buffer because in most buffers the pattern is  
> > not found.
> 
> Then he forgot the const decoration for the parameter.  No duping is  
> necessary:
> 
> void storeFoos(const(char)[] buffer, string pattern, Container c)
> {
>     ... // will result in compiler errors for given quote function, fix  
> that.
> }

Well, he tried that, but then his quote function wouldn't work and he needs it in other places as well. You know how they are ;-). Besides he thinks "const" is for wimps. He won't stop arguing until you prove to him that there is an actual bug in his code.

> >
> >> > Or another story. An enthusiastic programmer comes to you with a very
> >> > clever rewrite of a function. This is the original:
> >> >
> >> > T[] duplicate(T)(T[] src) {
> >> >    static if (is(T == invariant))
> >> >       return src.idup;
> >> >    else
> >> >       return src.dup;
> >> > }
> >> >
> >> > This is his improved version:
> >> >
> >> > T[] duplicate(T)(T[] src) {
> >> >    T tmp = src[$-1];
> >> >    src.length -= 1;
> >> >    src ~= tmp;
> >> >    return src;
> >> > }
> >> >
> >> > No need for static if! The extension is bound to re-allocate because  
> >> of
> >> > stomping rules. Will this always work, or is there a gotcha?
> >>
> >> He forgot to check for length 0.
> >>
> >
> > That he did. So now he goes back to the drawing board and adds an early  
> > return for length 0. Is his code correct now?
> 
> Yes.
> 
> I have a feeling you have some trick up your sleeve that you think makes  
> it incorrect :)

Well, I was wondering if it could be rewritten as:
T[] duplicate(T)(T[] src) {
    assert(src.length != 0);
    T tmp = src[$-1];
    src.length -= 1;
    src.length += 1;
    src[$-1] = tmp;
    return src;
}
and whether it's okay for the optimizer to do some simple arithmetic optimization. 



More information about the Digitalmars-d mailing list