www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - unsafe toString() behavior

reply lenfestey at geemail.com <lenfestey_member pathlink.com> writes:
import std.stdio;
import std.string;

void main() {
char[] x = toString(0);

// la de da...
x[0] = 'a';

// guess what i print
writefln("x=%s", toString(0));
}

It is because toString(uint) sometimes returns an array slice.

Aaron Lenfestey
Jun 26 2006
next sibling parent reply "Chris Miller" <chris dprogramming.com> writes:
On Mon, 26 Jun 2006 19:18:15 -0400, lenfestey at geemail.com  =

<lenfestey_member pathlink.com> wrote:

 import std.stdio;
 import std.string;

 void main() {
 char[] x =3D toString(0);

 // la de da...
 x[0] =3D 'a';

 // guess what i print
 writefln("x=3D%s", toString(0));
 }

 It is because toString(uint) sometimes returns an array slice.

 Aaron Lenfestey

In D you have to practice COW (copy-on-write) unless you are certain you= = are the only one using the memory.
Jun 26 2006
parent reply BCS <BCS_member pathlink.com> writes:
In article <op.tbr0mdsfpo9bzi moe>, Chris Miller says...
On Mon, 26 Jun 2006 19:18:15 -0400, lenfestey at geemail.com  =

<lenfestey_member pathlink.com> wrote:

 import std.stdio;
 import std.string;

 void main() {
 char[] x =3D toString(0);

 // la de da...
 x[0] =3D 'a';

 // guess what i print
 writefln("x=3D%s", toString(0));
 }

 It is because toString(uint) sometimes returns an array slice.

 Aaron Lenfestey

In D you have to practice COW (copy-on-write) unless you are certain you are the only one using the memory.

IM(h)O toString should *always* return a copy.
Jun 26 2006
next sibling parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"BCS" <BCS_member pathlink.com> wrote in message 
news:e7qd2l$j7g$1 digitaldaemon.com...
 IM(h)O toString should *always* return a copy.

I strongly agree.
Jun 26 2006
prev sibling next sibling parent reply "Chris Miller" <chris dprogramming.com> writes:
On Tue, 27 Jun 2006 00:44:05 -0400, BCS <BCS_member pathlink.com> wrote:=


 In article <op.tbr0mdsfpo9bzi moe>, Chris Miller says...
 On Mon, 26 Jun 2006 19:18:15 -0400, lenfestey at geemail.com  =3D

 <lenfestey_member pathlink.com> wrote:

 import std.stdio;
 import std.string;

 void main() {
 char[] x =3D3D toString(0);

 // la de da...
 x[0] =3D3D 'a';

 // guess what i print
 writefln("x=3D3D%s", toString(0));
 }

 It is because toString(uint) sometimes returns an array slice.

 Aaron Lenfestey

In D you have to practice COW (copy-on-write) unless you are certain =


 are the only one using the memory.

IM(h)O toString should *always* return a copy.

Nah, I disagree. Take MemoryStream for example, what if it has 2MB, you = = want that copied every toString. This COW is just a different method tha= n = what's common in other languages, and yields such a great performance = boost. If you want a copy, copy it. But if all you want to do is read th= e = value, what is the point in copying. Plus, where does this copying stop? Should every function returning an = array, or even a reference, make sure the caller gets a copy he can modi= fy? However, I think I would be in favor of some type of immutability, = provided it isn't so wordy and troublesome as C/C++'s.
Jun 26 2006
next sibling parent kris <foo bar.com> writes:
Chris Miller wrote:
 On Tue, 27 Jun 2006 00:44:05 -0400, BCS <BCS_member pathlink.com> wrote:
 
 In article <op.tbr0mdsfpo9bzi moe>, Chris Miller says...

 On Mon, 26 Jun 2006 19:18:15 -0400, lenfestey at geemail.com  =

 <lenfestey_member pathlink.com> wrote:

 import std.stdio;
 import std.string;

 void main() {
 char[] x =3D toString(0);

 // la de da...
 x[0] =3D 'a';

 // guess what i print
 writefln("x=3D%s", toString(0));
 }

 It is because toString(uint) sometimes returns an array slice.

 Aaron Lenfestey

In D you have to practice COW (copy-on-write) unless you are certain you are the only one using the memory.

IM(h)O toString should *always* return a copy.

Nah, I disagree. Take MemoryStream for example, what if it has 2MB, you want that copied every toString. This COW is just a different method than what's common in other languages, and yields such a great performance boost. If you want a copy, copy it. But if all you want to do is read the value, what is the point in copying. Plus, where does this copying stop? Should every function returning an array, or even a reference, make sure the caller gets a copy he can modify? However, I think I would be in favor of some type of immutability, provided it isn't so wordy and troublesome as C/C++'s.

Hear Hear! ;) Even if the immutable aspect could be supported for return-values only, we could then wrap our valuable immutables within an aggregate for those cases where immutability can be a considerable help (e.g. multi-threaded information sharing). That approach (return-values only) may be naiive on my part ~ would it notably simplify things in terms of implementation detail?
Jun 26 2006
prev sibling parent BCS <BCS_member pathlink.com> writes:
In article <op.tbshnsu0po9bzi moe>, Chris Miller says...
On Tue, 27 Jun 2006 00:44:05 -0400, BCS <BCS_member pathlink.com> wrote:=
 IM(h)O toString should *always* return a copy.

Nah, I disagree. Take MemoryStream for example, what if it has 2MB, you want that copied every toString. This COW is just a different method than what's common in other languages, and yields such a great performance boost. If you want a copy, copy it. But if all you want to do is read the value, what is the point in copying.

Overrides of object.toString might not be a good candidate for always copy, but toSting(intType) will copy in most cases (~ always copies) but an implementation might return a ptr to a static array for some cases (0-9 in the following example); char[] toString(uint i); { char[] ret; const static char[] map = "0123456789"; ret = map[i%10..i%10+1]; i/=10; while(i) { ret = map[i%10..i%10+1] ~ ret; i/=10; } return ret; } This would be a bad choice for COW, forget it once and problems start cropping up all over the place. A Simpler implementation might still get unrolled to this.
Plus, where does this copying stop? Should every function returning an
array, or even a reference, make sure the caller gets a copy he can modify?

No, only when it is ALWAYS a bug if the referenced data is changed.
Jun 27 2006
prev sibling next sibling parent reply Lionello Lunesu <lio lunesu.remove.com> writes:
Wouldn't this be solved by putting the string constants (assuming 
toString(0) returns an static constant) in read-only memory?

L.
Jun 26 2006
parent Carlos Santander <csantander619 gmail.com> writes:
Lionello Lunesu escribió:
 Wouldn't this be solved by putting the string constants (assuming 
 toString(0) returns an static constant) in read-only memory?
 
 L.

I also think this should be the solution. In fact, this is DMD's behavior on Linux (or at least used to be). -- Carlos Santander Bernal
Jun 27 2006
prev sibling parent kris <foo bar.com> writes:
BCS wrote:
 In article <op.tbr0mdsfpo9bzi moe>, Chris Miller says...
 
On Mon, 26 Jun 2006 19:18:15 -0400, lenfestey at geemail.com  =

<lenfestey_member pathlink.com> wrote:


import std.stdio;
import std.string;

void main() {
char[] x =3D toString(0);

// la de da...
x[0] =3D 'a';

// guess what i print
writefln("x=3D%s", toString(0));
}

It is because toString(uint) sometimes returns an array slice.

Aaron Lenfestey

In D you have to practice COW (copy-on-write) unless you are certain you are the only one using the memory.

IM(h)O toString should *always* return a copy.

But this particular issue is not so hard to resolve ... for instance, if a target-array was provided as part of the itoa() operation, there would be no need for heap activity or for aliasing. On the flip side, it would mean the method signatures are somwhat less succinct? Perhaps there are other detrimental aspects?
Jun 26 2006
prev sibling parent "Regan Heath" <regan netwin.co.nz> writes:
On Mon, 26 Jun 2006 23:18:15 +0000 (UTC), lenfestey at geemail.com  
<lenfestey_member pathlink.com> wrote:
 import std.stdio;
 import std.string;

 void main() {
 char[] x = toString(0);

 // la de da...
 x[0] = 'a';

 // guess what i print
 writefln("x=%s", toString(0));
 }

 It is because toString(uint) sometimes returns an array slice.

Theoretically "Copy on Write" should be used before writing to the string. Ideally the write should be detected and prevented by the compiler. Eventually I hope Walter can come up with a "const that works" for D :) Regan
Jun 26 2006