Thread overview | ||||||
---|---|---|---|---|---|---|
|
June 03, 2016 Problem with insertBack | ||||
---|---|---|---|---|
| ||||
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 |
June 03, 2016 Re: Problem with insertBack | ||||
---|---|---|---|---|
| ||||
Posted in reply to John Nixon | 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 not Right, because the cs stored on the stack is now pointing at a different heap-allocated array > 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? 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 |
June 03, 2016 Re: Problem with insertBack | ||||
---|---|---|---|---|
| ||||
Posted in reply to John Nixon | 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 not Here 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;} |
June 03, 2016 Re: Problem with insertBack | ||||
---|---|---|---|---|
| ||||
Posted in reply to ag0aep6g | On Friday, 3 June 2016 at 15:03:45 UTC, ag0aep6g wrote:
> 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 not
>
> Here 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;}
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 Nixon
|
Copyright © 1999-2021 by the D Language Foundation