So it seems like due to the low-level APIs that readlnImpl calls, it flies under the radar of Steve's detection.

I think using an Appender with the useExistingBuffer primitive would work, but would be suboptimal - each read can only use as many characters as read the last time, which would trigger quite a few allocation (whenever the line size increases). Please let me know whether this assessment is correct.

A possible solution would be to cache the last buffer and its maximum length in static variables inside readlnImpl. I think it's reasonable to say that readln is the owner of the char[] and you shouldn't take portions of it and expect they won't be changed. However, it will not trump over existing arrays.

Andrei

David Simcha wrote:


On Thu, Feb 4, 2010 at 12:10 AM, Andrei Alexandrescu <[email protected] <mailto:[email protected]>> wrote:

    David Simcha wrote:

        I recently filed bug 3673
        (http://d.puremagic.com/issues/show_bug.cgi?id=3763) and started
        looking at possible fixes.  This is a bug in
        std.stdio.readlnImpl().  However, the more I think about it the
        more I think the function needs to be completely rethought, not
        just patched.  I'm not sure if this is a high priority given
        that it has nothing to do with the language spec and TDPL but
        it's a pretty embarrassing quality of implementation issue.

        Anyhow, readlnImpl() takes a ref char[] and tries to recycle the
        memory to read in another line.  In doing so, it queries
        GC.capacity for the relevant memory block and resizes the array
        to the size of the memory block.  This is arguably unsafe in the
        general case because, if someone passes in a slice that starts
        at the beginning of a GC block to use as the buffer, everything
        else in the same GC block can get overwritten.  This massively
        violates the principle of least surprise.  On the other hand,
        when encapsulated in the higher level API of byLine(), it's both
        safe and efficient.


    Could you please give an example?

import std.stdio;

void main() {
    auto writer = File("foo.txt", "wb");
    foreach(i; 0..1000) {
        writer.write('a');
    }
    writer.writeln();
    writer.close();

    auto chars = new char[500];
    chars[] = 'b';
    auto buf = chars[0..100];

    auto reader = File("foo.txt", "rb");
    reader.readln(buf);
    writeln(chars[$ - 1]);  // a
    assert(chars[$ - 1] == 'b');  // FAILS.
}


------------------------------------------------------------------------

_______________________________________________
phobos mailing list
[email protected]
http://lists.puremagic.com/mailman/listinfo/phobos
_______________________________________________
phobos mailing list
[email protected]
http://lists.puremagic.com/mailman/listinfo/phobos

Reply via email to