digitalmars.D.learn - Problem with insertBack
- John Nixon (29/29) Jun 03 2016 I recently came across another problem with my program in D,
- Steven Schveighoffer (10/35) Jun 03 2016 You have inside your CS struct a pointer to a heap array. Then you
- ag0aep6g (16/36) Jun 03 2016 cs_array stores its data somewhere on the heap.
- John Nixon (8/48) Jun 03 2016 On Friday, 3 June 2016 at 15:03:45 UTC, ag0aep6g wrote:
I recently came across another problem with my program in D, found a minimal program showing it, and experimented a little with it as follows: import std.stdio; import std.container; struct CS{ char[] t; CS dup()const{ CS cs; cs.t = this.t.dup; return cs;} }; void main(){ Array!CS cs_array = make!(Array!CS)(); CS cs; cs.t = "bb".dup; cs_array.insertBack(cs); write("cs_array = ");foreach(i2;cs_array)write(i2);writeln(""); cs.t[0] = ("a".dup)[0];//this changes cs_array! write("cs_array = ");foreach(i2;cs_array)write(i2);writeln(""); cs.t = "c".dup;//but this does not write("cs_array = ");foreach(i2;cs_array)write(i2);writeln(""); return;} The first assignment to cs.t[0] changes cs_array as indicated, but the second to cs.t does not. Also if these two assignments are reversed, neither affects cs_array. What could be the explanation of this? Kind regards John Nixon
Jun 03 2016
On 6/3/16 10:34 AM, John Nixon wrote:I recently came across another problem with my program in D, found a minimal program showing it, and experimented a little with it as follows: import std.stdio; import std.container; struct CS{ char[] t; CS dup()const{ CS cs; cs.t = this.t.dup; return cs;} }; void main(){ Array!CS cs_array = make!(Array!CS)(); CS cs; cs.t = "bb".dup; cs_array.insertBack(cs); write("cs_array = ");foreach(i2;cs_array)write(i2);writeln(""); cs.t[0] = ("a".dup)[0];//this changes cs_array!You have inside your CS struct a pointer to a heap array. Then you change the heap array later. The CS element you put into the cs_array still points at the same piece of memory. Perhaps you meant to insert cs.dup?write("cs_array = ");foreach(i2;cs_array)write(i2);writeln(""); cs.t = "c".dup;//but this does notRight, because the cs stored on the stack is now pointing at a different heap-allocated arraywrite("cs_array = ");foreach(i2;cs_array)write(i2);writeln(""); return;} The first assignment to cs.t[0] changes cs_array as indicated, but the second to cs.t does not. Also if these two assignments are reversed, neither affects cs_array. What could be the explanation of this?Right, because if the stack is pointing at a different array than the cs_array[0], then altering won't affect cs_array[0]. -Steve
Jun 03 2016
On 06/03/2016 04:34 PM, John Nixon wrote:import std.stdio; import std.container; struct CS{ char[] t; CS dup()const{ CS cs; cs.t = this.t.dup; return cs;} };Aside: No semicolon after struct declarations in D.void main(){ Array!CS cs_array = make!(Array!CS)();cs_array stores its data somewhere on the heap.CS cs;cs is on the stack.cs.t = "bb".dup;But cs.t's data is on the heap, like cs_array's. cs.t contains a pointer to it.cs_array.insertBack(cs);This copies cs to cs_array's heap. The pointer in cs.t is being copied, but the data that it points to is not being copied. So cs.t and cs_array[0].t contain two distinct but equal pointers now. Since they're equal, they refer to the same data.write("cs_array = ");foreach(i2;cs_array)write(i2);writeln(""); cs.t[0] = ("a".dup)[0];//this changes cs_array!This is expected since cs.t and cs_array[0].t point to the same location. A change to the data through one of them is visible to the other.write("cs_array = ");foreach(i2;cs_array)write(i2);writeln(""); cs.t = "c".dup;//but this does notHere you're not writing through the pointer in cs.t, but rather you're assigning a whole new one. Since the pointers in cs.t and cs_array[0].t are independent of each other, they now point to different locations, with different data.write("cs_array = ");foreach(i2;cs_array)write(i2);writeln(""); return;}
Jun 03 2016
On Friday, 3 June 2016 at 15:03:45 UTC, ag0aep6g wrote:On 06/03/2016 04:34 PM, John Nixon wrote:On Friday, 3 June 2016 at 15:03:45 UTC, ag0aep6g wrote: Thanks very much to you and Steve for the detailed explanation. By the way I did try insertBack(cs.dup) but wasn't sure what I was doing. It seems that I just need to add all the .dup 's when needed to make my program work and find out a procedure to make sure I don't miss any. John Nixonimport std.stdio; import std.container; struct CS{ char[] t; CS dup()const{ CS cs; cs.t = this.t.dup; return cs;} };Aside: No semicolon after struct declarations in D.void main(){ Array!CS cs_array = make!(Array!CS)();cs_array stores its data somewhere on the heap.CS cs;cs is on the stack.cs.t = "bb".dup;But cs.t's data is on the heap, like cs_array's. cs.t contains a pointer to it.cs_array.insertBack(cs);This copies cs to cs_array's heap. The pointer in cs.t is being copied, but the data that it points to is not being copied. So cs.t and cs_array[0].t contain two distinct but equal pointers now. Since they're equal, they refer to the same data.write("cs_array = ");foreach(i2;cs_array)write(i2);writeln(""); cs.t[0] = ("a".dup)[0];//this changes cs_array!This is expected since cs.t and cs_array[0].t point to the same location. A change to the data through one of them is visible to the other.write("cs_array = ");foreach(i2;cs_array)write(i2);writeln(""); cs.t = "c".dup;//but this does notHere you're not writing through the pointer in cs.t, but rather you're assigning a whole new one. Since the pointers in cs.t and cs_array[0].t are independent of each other, they now point to different locations, with different data.write("cs_array = ");foreach(i2;cs_array)write(i2);writeln(""); return;}
Jun 03 2016