This program causes two asserts on Win32:
import std.stdio;
import std.file;
import core.memory;
void main()
{
std.file.write("testread", "abcd\n0123456789abcde\n");
File f = File("testread", "rb");
char[] ln = new char[2];
f.readln(ln);
assert(ln == "abcd\n");
char[] t = ln[0..2];
t ~= 't'; // stomps ln
assert(t == "abt");
assert(ln == "abcd\n"); // fails
// it can get also stomp the array length
ln = new char[4];
f.readln(ln);
assert(ln == "0123456789abcde\n");
auto bi = GC.query(ln.ptr);
assert(bi.base == ln.ptr);
assert(bi.attr & GC.BlkAttr.APPENDABLE);
int len = ln.ptr[bi.size - 1]; // last byte should be allocated array size
assert(ln.length <= len && len < bi.size); // fails: len = 10
}
shows that readln fills the memory of arrays with data without respecting the "allocation length" also stored for arrays.
There are different implementations for DigitalMars, Microsoft and GCC runtime, so the behaviour might be slightly different, but all assume that the passed array is GC.malloced, starts at the allocation block and has size GC.sizeOf(arr.ptr).
Comment #1 by r.sagitario — 2014-12-12T10:35:32Z
This shows that the current implementation also adds an unnecesary allocation when supplying stack allocated arrays as an initial buffer.
void main()
{
std.file.write("testread", "abcd\n");
File f = File("testread", "rb");
char[100] buf;
ln = buf[];
f.readln(ln);
assert(ln.ptr == buf.ptr);
}
*** Issue 14005 has been marked as a duplicate of this issue. ***
Comment #4 by mk — 2015-03-19T22:36:10Z
*** Issue 14310 has been marked as a duplicate of this issue. ***
Comment #5 by code — 2015-03-24T13:36:57Z
As an intermediate replacement it is possible to use byLine.
Comment #6 by acehreli — 2015-03-24T13:59:39Z
Both of the bugs that are marked as duplicates of this one use byLine. (However, bug 14005 seems to be cured at this time.)
Ali
Comment #7 by schveiguy — 2015-03-24T14:28:31Z
(In reply to Martin Nowak from comment #5)
> As an intermediate replacement it is possible to use byLine.
Not really. readln does not do the same thing as byLine.
I don't know how you would use byline instead of readln in the OP code. byLine is not really meant to be a "read a line here or there" type of operation, it's meant to exhaust the stream a line at a time.
Comment #8 by github-bugzilla — 2015-07-13T15:05:12Z