digitalmars.D.learn - Confused about class equality
- strtr (55/55) Apr 02 2010 The program below outputs, as I would expect :
- Justin Spahr-Summers (5/55) Apr 02 2010 You may want to try reducing the code within your "larger project" to
- strtr (3/9) Apr 02 2010 The main starting from "I i1 = null;" is actual code from my program. Th...
- strtr (18/18) Apr 02 2010 What I probably mean to ask is :
- Jacob Carlborg (7/25) Apr 03 2010 I would guess:
- strtr (6/36) Apr 03 2010 Wouldn't that simply result in the following?
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (14/77) Apr 03 2010 The code works as expected with 2.042
- strtr (3/22) Apr 04 2010 I probably wasn't clear about what exactly my problem is :
- Justin Spahr-Summers (7/31) Apr 04 2010 Again, without seeing the *actual* code that you are using, it's hard to...
- strtr (4/10) Apr 04 2010 But also, the question remains :)
- bearophile (5/6) Apr 04 2010 I think this questions is meaningless. Those pointers don't point to obj...
- strtr (10/19) Apr 06 2010 The subject wasn't for nothing :)
- bearophile (12/12) Apr 06 2010 Time ago I have told Walter that adding images with pointers and boxes t...
- Justin Spahr-Summers (5/27) Apr 06 2010 I think he said that he has two distinct object references, but the
- strtr (20/25) Apr 06 2010 I've added this exact sequence:
- Justin Spahr-Summers (7/36) Apr 06 2010 Hmm, that is pretty weird. Are you doing any casts anywhere, or any
- strtr (6/15) Apr 06 2010 A search for cast didn't show any related casts.
- Justin Spahr-Summers (5/13) Apr 07 2010 Without actual explicit casting, I don't know how it'd be possible to
- strtr (4/25) Apr 06 2010 I totally agree on the visual help!
The program below outputs, as I would expect : Same Value. Same Object. 3 : 44E15C 0000 3 : 44E15C 0000 5 : 44E15C 0000 5 : 44E15C 0000 Now what would it mean if it were to output : Same Value. 3 : 5B536C 59D020 3 : 59CE0C 59CEF0 5 : 5B536C 59D020 5 : 59CE0C 59CEF0 (Output from essentially the same piece of code within a larger project) Not the same object, but still able to change it with one call. What is it I don't get? ------ module main; import std.stdio; import std.string; interface I{ char[] toString(); int value(); void value(int v); } class C : I{ private int _value; this(int v){ _value = v; } char[] toString(){ return format(_value); }; int value(){ return _value; }; void value(int v){ _value = v; }; } private I[3][3] arr; public I getI( int x, int y){ return arr[x][y]; } public void setI( int x, int y, I i ){ arr[x][y]= i; } void main(){ C c = new C(3); setI( 0, 0, c ); setI( 1, 2, c ); I i1 = null; I i2 = null; i1 = getI(0,0); i2 = getI(1,2); if( i1 !is null && i2 !is null && i2.value == i1.value ) { writefln("Same Value."); if( i2 is i1 ) writefln("Same Object."); writefln( i2.toString()," : ",i2.__vptr," ",i2.__monitor); writefln( i1.toString(), " : ", i1.__vptr," ",i1.__monitor); i1.value = 5; writefln( i2.toString()," : ",i2.__vptr," ",i2.__monitor); writefln( i1.toString(), " : ", i1.__vptr," ",i1.__monitor); } }
Apr 02 2010
On Fri, 02 Apr 2010 22:36:40 -0400, strtr <strtr spam.com> wrote:The program below outputs, as I would expect : Same Value. Same Object. 3 : 44E15C 0000 3 : 44E15C 0000 5 : 44E15C 0000 5 : 44E15C 0000 Now what would it mean if it were to output : Same Value. 3 : 5B536C 59D020 3 : 59CE0C 59CEF0 5 : 5B536C 59D020 5 : 59CE0C 59CEF0 (Output from essentially the same piece of code within a larger project) Not the same object, but still able to change it with one call. What is it I don't get? ------ module main; import std.stdio; import std.string; interface I{ char[] toString(); int value(); void value(int v); } class C : I{ private int _value; this(int v){ _value = v; } char[] toString(){ return format(_value); }; int value(){ return _value; }; void value(int v){ _value = v; }; } private I[3][3] arr; public I getI( int x, int y){ return arr[x][y]; } public void setI( int x, int y, I i ){ arr[x][y]= i; } void main(){ C c = new C(3); setI( 0, 0, c ); setI( 1, 2, c ); I i1 = null;You may want to try reducing the code within your "larger project" to the smallest use case where the problem still occurs, because, I agree, the code as written will always result in the same object, since you allocate only one.
Apr 02 2010
Justin Spahr-Summers Wrote:On Fri, 02 Apr 2010 22:36:40 -0400, strtr <strtr spam.com> wrote: You may want to try reducing the code within your "larger project" to the smallest use case where the problem still occurs, because, I agree, the code as written will always result in the same object, since you allocate only one.The main starting from "I i1 = null;" is actual code from my program. The getI function is also the same and no code resides in between, nor is it multi-threaded. Within this setting, how can you manipulate the objects in arr(which is larger in the actual code) to get the strange output?
Apr 02 2010
What I probably mean to ask is : In the code below, for what kind of i1 and i2 would the output be like this : --------- Same Value. 3 : 5B536C 59D020 3 : 59CE0C 59CEF0 5 : 5B536C 59D020 5 : 59CE0C 59CEF0 --------- if( i1 !is null && i2 !is null && i2.value == i1.value ) { writefln("Same Value."); if( i2 is i1 ) writefln("Same Object."); writefln( i2.toString()," : ",i2.__vptr," ",i2.__monitor); writefln( i1.toString(), " : ", i1.__vptr," ",i1.__monitor); i1.value = 5; writefln( i2.toString()," : ",i2.__vptr," ",i2.__monitor); writefln( i1.toString(), " : ", i1.__vptr," ",i1.__monitor); }
Apr 02 2010
On 4/3/10 07:03, strtr wrote:What I probably mean to ask is : In the code below, for what kind of i1 and i2 would the output be like this : --------- Same Value. 3 : 5B536C 59D020 3 : 59CE0C 59CEF0 5 : 5B536C 59D020 5 : 59CE0C 59CEF0 --------- if( i1 !is null&& i2 !is null&& i2.value == i1.value ) { writefln("Same Value."); if( i2 is i1 ) writefln("Same Object."); writefln( i2.toString()," : ",i2.__vptr," ",i2.__monitor); writefln( i1.toString(), " : ", i1.__vptr," ",i1.__monitor); i1.value = 5; writefln( i2.toString()," : ",i2.__vptr," ",i2.__monitor); writefln( i1.toString(), " : ", i1.__vptr," ",i1.__monitor); }I would guess: i1 = new I; i2 = new I; They are two different instance of "I" but containing the same value. When comparing two objects using "is", the addresses are compared and not the data in the object, i.e. instance variables.
Apr 03 2010
Jacob Carlborg Wrote:On 4/3/10 07:03, strtr wrote:Wouldn't that simply result in the following? 3 : 5B536C 59D020 3 : 59CE0C 59CEF0 5 : 5B536C 59D020 3 : 59CE0C 59CEF0What I probably mean to ask is : In the code below, for what kind of i1 and i2 would the output be like this : --------- Same Value. 3 : 5B536C 59D020 3 : 59CE0C 59CEF0 5 : 5B536C 59D020 5 : 59CE0C 59CEF0 --------- if( i1 !is null&& i2 !is null&& i2.value == i1.value ) { writefln("Same Value."); if( i2 is i1 ) writefln("Same Object."); writefln( i2.toString()," : ",i2.__vptr," ",i2.__monitor); writefln( i1.toString(), " : ", i1.__vptr," ",i1.__monitor); i1.value = 5; writefln( i2.toString()," : ",i2.__vptr," ",i2.__monitor); writefln( i1.toString(), " : ", i1.__vptr," ",i1.__monitor); }I would guess: i1 = new I; i2 = new I; They are two different instance of "I" but containing the same value. When comparing two objects using "is", the addresses are compared and not the data in the object, i.e. instance variables.
Apr 03 2010
strtr wrote:The program below outputs, as I would expect : Same Value. Same Object. 3 : 44E15C 0000 3 : 44E15C 0000 5 : 44E15C 0000 5 : 44E15C 0000 Now what would it mean if it were to output : Same Value. 3 : 5B536C 59D020 3 : 59CE0C 59CEF0 5 : 5B536C 59D020 5 : 59CE0C 59CEF0 (Output from essentially the same piece of code within a larger project) Not the same object, but still able to change it with one call. What is it I don't get? ------ module main; import std.stdio; import std.string; interface I{ char[] toString(); int value(); void value(int v); } class C : I{ private int _value; this(int v){ _value = v; } char[] toString(){ return format(_value); }; int value(){ return _value; }; void value(int v){ _value = v; }; } private I[3][3] arr; public I getI( int x, int y){ return arr[x][y]; } public void setI( int x, int y, I i ){ arr[x][y]= i; } void main(){ C c = new C(3); setI( 0, 0, c ); setI( 1, 2, c ); I i1 = null; I i2 = null; i1 = getI(0,0); i2 = getI(1,2); if( i1 !is null && i2 !is null && i2.value == i1.value ) { writefln("Same Value."); if( i2 is i1 ) writefln("Same Object."); writefln( i2.toString()," : ",i2.__vptr," ",i2.__monitor); writefln( i1.toString(), " : ", i1.__vptr," ",i1.__monitor); i1.value = 5; writefln( i2.toString()," : ",i2.__vptr," ",i2.__monitor); writefln( i1.toString(), " : ", i1.__vptr," ",i1.__monitor); } }The code works as expected with 2.042 I had to modify the toString() functions to return string, and say "override" in C's toString definition; and had to modify the writefln() calls: writefln("%s : %s %s", i2.toString(), i2.__vptr, i2.__monitor); The output: Same Value. Same Object. 3 : 806D3F4 0 3 : 806D3F4 0 5 : 806D3F4 0 5 : 806D3F4 0 Ali
Apr 03 2010
Ali Çehreli Wrote:The code works as expected with 2.042 I had to modify the toString() functions to return string, and say "override" in C's toString definition; and had to modify the writefln() calls: writefln("%s : %s %s", i2.toString(), i2.__vptr, i2.__monitor); The output: Same Value. Same Object. 3 : 806D3F4 0 3 : 806D3F4 0 5 : 806D3F4 0 5 : 806D3F4 0 AliI probably wasn't clear about what exactly my problem is : Somehow in my (D1) program two object references have different vpointers/monitors and thus fail in "is" equality but I can change both objects with one call.
Apr 04 2010
On Sun, 04 Apr 2010 13:14:29 -0400, strtr <strtr spam.com> wrote:Ali Çehreli Wrote:Again, without seeing the *actual* code that you are using, it's hard to say. The first thing that comes to mind is maybe a syntactical mistake, such as "i1.value = i2.value" when a comparison was intended, but there could be something else at play too, and without seeing the code (which is not the same as what you included in your first message) it's impossible to ascertain.The code works as expected with 2.042 I had to modify the toString() functions to return string, and say "override" in C's toString definition; and had to modify the writefln() calls: writefln("%s : %s %s", i2.toString(), i2.__vptr, i2.__monitor); The output: Same Value. Same Object. 3 : 806D3F4 0 3 : 806D3F4 0 5 : 806D3F4 0 5 : 806D3F4 0 AliI probably wasn't clear about what exactly my problem is : Somehow in my (D1) program two object references have different vpointers/monitors and thus fail in "is" equality but I can change both objects with one call.
Apr 04 2010
== Quote from Justin Spahr-Summers (Justin.SpahrSummers gmail.com)'s articleAgain, without seeing the *actual* code that you are using, it's hard to say. The first thing that comes to mind is maybe a syntactical mistake, such as "i1.value = i2.value" when a comparison was intended, but there could be something else at play too, and without seeing the code (which is not the same as what you included in your first message) it's impossible to ascertain.But also, the question remains :) (I haven't been able to replicate it in small program but the main is actual code.) Is it possible to have different vpointers/monitors pointing to the same object?
Apr 04 2010
strtr:Is it possible to have different vpointers/monitors pointing to the same object?I think this questions is meaningless. Those pointers don't point to objects. And the "is" operator compared class references, not vpointers/monitors. Bye, bearophile
Apr 04 2010
bearophile Wrote:strtr:The subject wasn't for nothing :) How I understand it now, vptr points to the Class's vtable. This would mean they should be the same for references to the same object or can these references also hold a pointer to a pointer to the vtable? I'm not sure where the monitor points to, though. The problem surfaces when I wanted to do a simple check for objects equality between references. I though I should use "is" for this. But to my astonishment it failed even though I know the references point to the same object, I think. I checked whether the references pointed to the same object by giving all objects a unique value and changing this value via one of the references and then checking whether the value was the same for the other reference. Conclusion: two references fail "is", but changing the value via one of the references also changed the value got via the other reference. My solution for now is simply checking for equality via this unique value but I hoped I could use "is" for this :) I suspect I totally misunderstand something; hope to learn something again :)Is it possible to have different vpointers/monitors pointing to the same object?I think this questions is meaningless. Those pointers don't point to objects. And the "is" operator compared class references, not vpointers/monitors. Bye, bearophile
Apr 06 2010
Time ago I have told Walter that adding images with pointers and boxes to the D docs, that represent the main data structures used in D, can help a lot the understanding and usage of D. When you *see* the data structure in an image, understanding what happens and how to write program gets easy. So I'd like to see images of the virtual table, an object, interface, etc. A class reference is a pointer, that is the index (an integer number) of the first byte of RAM of a segment of RAM. The segment of ram contains the class instance data, plus two more pointers at its start, one to the virtual table, and one to the monitor. The virtual table is a struct that contains indirect pointers to the virtual functions and more. I don't know the layout of the virtual tables in dmd. And I have no idea how the monitor is structured, it's a mystery for me still. I am learning still. All the instances of a single class point to the same virtual table. Instances of different classes contain pointers to different virtual tables. All objects in D have a pointer to VPT, even classes with no virtual methods. (Structs have no pointer to monitor and vtbl, but they can have a pointer to outer scope if they are not static. This is true for classes too, and there is a little more complexity coming from template instantiations inside functions in D). When you instantiate a class you create a new section of memory that contains the class members, plus the two pointers. You can have more than one reference to the same object. And two distinct objects in memory can have the same data into their members. The "is" operator just compares the class instances, if they are equal (the optimizer can avoid some tests if it knows the objects are surely different, because it knows the static types). The == among class instances does several things. See D docs page about operator overloading. But basically it tests if the references are the same. If it's true, then they are two references to the same class instance, so they must be equal, and the == returns true. If the references are different it tests for equality of all members, and returns true if they are all equal, otherwise false. Bye, bearophile
Apr 06 2010
On Tue, 06 Apr 2010 21:15:02 -0400, bearophile <bearophileHUGS lycos.com> wrote:Time ago I have told Walter that adding images with pointers and boxes to the D docs, that represent the main data structures used in D, can help a lot the understanding and usage of D. When you *see* the data structure in an image, understanding what happens and how to write program gets easy. So I'd like to see images of the virtual table, an object, interface, etc. A class reference is a pointer, that is the index (an integer number) of the first byte of RAM of a segment of RAM. The segment of ram contains the class instance data, plus two more pointers at its start, one to the virtual table, and one to the monitor. The virtual table is a struct that contains indirect pointers to the virtual functions and more. I don't know the layout of the virtual tables in dmd. And I have no idea how the monitor is structured, it's a mystery for me still. I am learning still. All the instances of a single class point to the same virtual table. Instances of different classes contain pointers to different virtual tables. All objects in D have a pointer to VPT, even classes with no virtual methods. (Structs have no pointer to monitor and vtbl, but they can have a pointer to outer scope if they are not static. This is true for classes too, and there is a little more complexity coming from template instantiations inside functions in D). When you instantiate a class you create a new section of memory that contains the class members, plus the two pointers. You can have more than one reference to the same object. And two distinct objects in memory can have the same data into their members. The "is" operator just compares the class instances, if they are equal (the optimizer can avoid some tests if it knows the objects are surely different, because it knows the static types). The == among class instances does several things. See D docs page about operator overloading. But basically it tests if the references are the same. If it's true, then they are two references to the same class instance, so they must be equal, and the == returns true. If the references are different it tests for equality of all members, and returns true if they are all equal, otherwise false. Bye, bearophileI think he said that he has two distinct object references, but the value stored in the object(s) changes by changing either one. In other words, we'd need to see the code.
Apr 06 2010
Justin Spahr-Summers Wrote:I think he said that he has two distinct object references, but the value stored in the object(s) changes by changing either one. In other words, we'd need to see the code.I've added this exact sequence: if( c1 !is null ) { c1.value = 1; if( c2 !is null ) { c2.value = 2; if( c1 !is c2 ) { c1.value = 3; assert(c2.value == 2 ); } c2.value = 0; } c1.value = 0; } To my understanding this should never fails, yet it does. AssertError Failure
Apr 06 2010
On Tue, 06 Apr 2010 22:41:43 -0400, strtr <strtr spam.com> wrote:Justin Spahr-Summers Wrote:Hmm, that is pretty weird. Are you doing any casts anywhere, or any pointer arithmetic/tricks? The only thing that I can think of is that you might've somehow unintentionally fooled the compiler/runtime by coercing some types somewhere. If not, it might comprise a valid bug report.I think he said that he has two distinct object references, but the value stored in the object(s) changes by changing either one. In other words, we'd need to see the code.I've added this exact sequence: if( c1 !is null ) { c1.value = 1; if( c2 !is null ) { c2.value = 2; if( c1 !is c2 ) { c1.value = 3; assert(c2.value == 2 ); } c2.value = 0; } c1.value = 0; } To my understanding this should never fails, yet it does. AssertError Failure
Apr 06 2010
Justin Spahr-Summers Wrote:Hmm, that is pretty weird. Are you doing any casts anywhere, or any pointer arithmetic/tricks?A search for cast didn't show any related casts. Do you maybe know another thing to check? I do throw references around and there are a lot of implicit casts to extended interfaces.The only thing that I can think of is that you might've somehow unintentionally fooled the compiler/runtime by coercing some types somewhere.Don't the different vptrs also hint to this?If not, it might comprise a valid bug report.Trying to find a minimal version.. might take some time :(
Apr 06 2010
On Tue, 06 Apr 2010 23:35:01 -0400, strtr <strtr spam.com> wrote:Justin Spahr-Summers Wrote:Without actual explicit casting, I don't know how it'd be possible to invoke behavior like that. Maybe an object of class X getting implicitly converted to interface A and then explicitly cast to class Y? It'd have to be pretty convoluted.Hmm, that is pretty weird. Are you doing any casts anywhere, or any pointer arithmetic/tricks?A search for cast didn't show any related casts. Do you maybe know another thing to check? I do throw references around and there are a lot of implicit casts to extended interfaces.
Apr 07 2010
bearophile Wrote:Time ago I have told Walter that adding images with pointers and boxes to the D docs, that represent the main data structures used in D, can help a lot the understanding and usage of D. When you *see* the data structure in an image, understanding what happens and how to write program gets easy. So I'd like to see images of the virtual table, an object, interface, etc. A class reference is a pointer, that is the index (an integer number) of the first byte of RAM of a segment of RAM. The segment of ram contains the class instance data, plus two more pointers at its start, one to the virtual table, and one to the monitor. The virtual table is a struct that contains indirect pointers to the virtual functions and more. I don't know the layout of the virtual tables in dmd. And I have no idea how the monitor is structured, it's a mystery for me still. I am learning still. All the instances of a single class point to the same virtual table. Instances of different classes contain pointers to different virtual tables. All objects in D have a pointer to VPT, even classes with no virtual methods. (Structs have no pointer to monitor and vtbl, but they can have a pointer to outer scope if they are not static. This is true for classes too, and there is a little more complexity coming from template instantiations inside functions in D). When you instantiate a class you create a new section of memory that contains the class members, plus the two pointers. You can have more than one reference to the same object. And two distinct objects in memory can have the same data into their members. The "is" operator just compares the class instances, if they are equal (the optimizer can avoid some tests if it knows the objects are surely different, because it knows the static types). The == among class instances does several things. See D docs page about operator overloading. But basically it tests if the references are the same. If it's true, then they are two references to the same class instance, so they must be equal, and the == returns true. If the references are different it tests for equality of all members, and returns true if they are all equal, otherwise false. Bye, bearophileI totally agree on the visual help! I think I'll create such a diagram after I get my brain mess cleaned up :) Your explanation doesn't differ (but does expand ;) from my understanding of the whole class implementation subject. I still do not know what a monitor is though ;)
Apr 06 2010