www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - Access violation with interface as key type

reply Xenon <Xenon_member pathlink.com> writes:
I see no reason why this code should not work. However, it consistently crashes
on execution. Compiled with >dmd bug.d -ofbug.exe

interface A {
int x();
}

class B : A {
int x() {
return 1;
}
}

int main(char[][] args) {	
B foo = new B();

int[B] arrayB;
arrayB[foo] = 1; // this works
printf("Ok B\n");

int[A] arrayA;
arrayA[foo] = 1; // Error: Access Violation
printf("Ok A\n");

return 0;
}

If I define A as an abstract class instead, changing the declaration to

abstract class A {
abstract int x();
}

the example works as expected. Is this a bug, or a strange "feature"?
Sep 28 2005
next sibling parent Xenon <Xenon_member pathlink.com> writes:
In article <dhffam$12jr$1 digitaldaemon.com>, Xenon says...
I see no reason why this code should not work. However, it consistently crashes
on execution. Compiled with >dmd bug.d -ofbug.exe

I forgot to mention; version 0.133 on Windows.
Sep 28 2005
prev sibling parent reply Holger <Holger_member pathlink.com> writes:
In article <dhffam$12jr$1 digitaldaemon.com>, Xenon says...
I see no reason why this code should not work. However, it consistently crashes
on execution. Compiled with >dmd bug.d -ofbug.exe

interface A {
int x();
}

class B : A {
int x() {
return 1;
}
}

int main(char[][] args) {	
B foo = new B();

int[B] arrayB;
arrayB[foo] = 1; // this works
printf("Ok B\n");

int[A] arrayA;
arrayA[foo] = 1; // Error: Access Violation
printf("Ok A\n");

return 0;
}

If I define A as an abstract class instead, changing the declaration to

abstract class A {
abstract int x();
}

the example works as expected. Is this a bug, or a strange "feature"?

I'm not sure if it is a bug, at least it is a known issue. Perhaps someone more knowledgeable could shed a light on this? Cheers, Holger
Sep 29 2005
parent reply Xenon <Xenon_member pathlink.com> writes:
In article <dhgd66$1qsq$1 digitaldaemon.com>, Holger says...
I'm not sure if it is a bug, at least it is a known issue.
Perhaps someone more knowledgeable could shed a light on this?

Maybe the real bug is that the compiler doesn't produce an error in this situation, but generates incorrect (segfaulting) code instead? It should be trivial to check whether the key type is an interface and display an appropriate message.
Sep 29 2005
parent reply =?ISO-8859-1?Q?Jari-Matti_M=E4kel=E4?= <jmjmak invalid_utu.fi> writes:
Xenon wrote:
 In article <dhgd66$1qsq$1 digitaldaemon.com>, Holger says...
 
I'm not sure if it is a bug, at least it is a known issue.
Perhaps someone more knowledgeable could shed a light on this?

Maybe the real bug is that the compiler doesn't produce an error in this situation, but generates incorrect (segfaulting) code instead? It should be trivial to check whether the key type is an interface and display an appropriate message.

I really hope Walter is someday able to allow similar interfaces that they do have in Java. I think the problem is that D seems to handle interfaces and classes as separate structures.
Sep 29 2005
parent reply Derek Parnell <derek psych.ward> writes:
On Fri, 30 Sep 2005 02:12:06 +0300, Jari-Matti Mäkelä wrote:

 Xenon wrote:
 In article <dhgd66$1qsq$1 digitaldaemon.com>, Holger says...
 
I'm not sure if it is a bug, at least it is a known issue.
Perhaps someone more knowledgeable could shed a light on this?

Maybe the real bug is that the compiler doesn't produce an error in this situation, but generates incorrect (segfaulting) code instead? It should be trivial to check whether the key type is an interface and display an appropriate message.

I really hope Walter is someday able to allow similar interfaces that they do have in Java. I think the problem is that D seems to handle interfaces and classes as separate structures.

Excuse my Java/C# ignorance, but in my mind interfaces and classes are two very different beasts. I view interfaces to be no more than a hinting mechanism for the compiler so it can verify that all the required methods for a class have been declared. Plus it can supply a default implementation if one is required. However, the way I see people trying to use interfaces in D leads me to suspect that these people assume that interfaces are really a type of class; a subset in some way maybe. Kind of like a light weight class, but I can't quite grok what this concept of an interface is. The way they are documented in D seems logical and simple to understand and use. To me an array of interfaces is weird. It's like asking for an array of typedefs (not an array of the new data type but of the typedef itself). I've read stuff on the interface concept in Java and I still don't quite get it. Maybe someone here can enlighten me by not speaking in Java jargon (that is, straight forward English instead). -- Derek (skype: derek.j.parnell) Melbourne, Australia 30/09/2005 9:40:32 AM
Sep 29 2005
next sibling parent =?ISO-8859-1?Q?Thomas_K=FChne?= <thomas-dloop kuehne.cn> writes:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Derek Parnell schrieb:
 However, the way I see people trying to use interfaces in D leads me to
 suspect that these people assume that interfaces are really a type of
 class; a subset in some way maybe. Kind of like a light weight class, but I
 can't quite grok what this concept of an interface is. The way they are
 documented in D seems logical and simple to understand and use.
 
 To me an array of interfaces is weird. It's like asking for an array of
 typedefs (not an array of the new data type but of the typedef itself).
 
 I've read stuff on the interface concept in Java and I still don't quite
 get it. Maybe someone here can enlighten me by not speaking in Java jargon
 (that is, straight forward English instead).

There are at least 2 common uses for interfaces: *** sample A *** class Snake {} class Car {} Both classes are abstract representations of moving objects, thus the use of an interface to get the current speed interface ObjectInMotion { uint getCurrentSpeed(); } class Snake : ObjectInMotion { .... } class Car : ObjectInMotion { .... } does make sense, whereas a common base class is sometimes to restrictive. *** sample B *** Integrating closed source classes into an existing framework often requires the use of interfaces. class ClosedSource { int membercount(); } class Frame { int getTotalNumberOfMembers(); } Let's integrate the ClosedSource class into our framework: interface IFrame { int getTotalNumberOfMembers(); } class Frame : IFrame { .... } class Integrated : ClosedSource, IFrame { int getTotalNumberOfMembers(){ return membercount(); } } Thomas -----BEGIN PGP SIGNATURE----- iD8DBQFDPOqO3w+/yD4P9tIRAnPwAKDTkglOGxoEDkIyfTMNecVx9mnhNACfZKWA ECqJF8PZqysAWHOUF0o3zPc= =5SWS -----END PGP SIGNATURE-----
Sep 30 2005
prev sibling parent reply Mike Parker <aldacron71 yahoo.com> writes:
Derek Parnell wrote:
 On Fri, 30 Sep 2005 02:12:06 +0300, Jari-Matti Mäkelä wrote:

 However, the way I see people trying to use interfaces in D leads me to
 suspect that these people assume that interfaces are really a type of
 class; a subset in some way maybe. Kind of like a light weight class, but I
 can't quite grok what this concept of an interface is. The way they are
 documented in D seems logical and simple to understand and use.
 
 To me an array of interfaces is weird. It's like asking for an array of
 typedefs (not an array of the new data type but of the typedef itself).

An array of interfaces makes no sense when you think of it as 'an array interface declarations', but when you think in terms of 'an array of objects that implement a given interface', then it should make sense. When an interface is referenced in code, it's a way of allowing you to access several different implementations of an interface without the need to know the details of the implementation. If ClassA and ClassB are in two seperate class heirarchies, but they both implement MyInterface, then I should be able to manipulate them via a MyInterface reference (which is a reference to an object instance which implements the interface, not the interface itself). By declaring an array of MyInterfaces, or an aa with MyInterface keys, I should be able to use instances of ClassA and ClassB as members of the array or as aa keys and expect to be able to call MyInterface methods on them. An interface is another way to 'view' a class which implements it. Another way to look at it is to consider the two basic types of inheritance: implementation inheritance and interface inheritance. C++ makes no distiction between the two, but C++ programmers make a distinction by referring to interface classes as 'pure virtual'. The Java designers decided that multiple inheritance is a Really Bad Thing when you inherit the implementation, but is acceptable when inheriting the interface. So the 'interface' type was created to enforce the distinction between interface inheritance and implementation inheritance. If you equate an 'interface' with a 'pure virtual' C++ class, you should start to see why D interfaces appear broken in some regards.
Sep 30 2005
parent reply =?ISO-8859-1?Q?Jari-Matti_M=E4kel=E4?= <jmjmak invalid_utu.fi> writes:
Mike Parker wrote:
 An array of interfaces makes no sense when you think of it as 'an array 
 interface declarations', but when you think in terms of 'an array of 
 objects that implement a given interface', then it should make sense. 
 When an interface is referenced in code, it's a way of allowing you to 
 access several different implementations of an interface without the 
 need to know the details of the implementation. If ClassA and ClassB are 
 in two seperate class heirarchies, but they both implement MyInterface, 
 then I should be able to manipulate them via a MyInterface reference 
 (which is a reference to an object instance which implements the 
 interface, not the interface itself). By declaring an array of 
 MyInterfaces, or an aa with MyInterface keys, I should be able to use 
 instances of ClassA and ClassB as members of the array or as aa keys and 
 expect to be able to call MyInterface methods on them. An interface is 
 another way to 'view' a class which implements it.
 
 Another way to look at it is to consider the two basic types of 
 inheritance: implementation inheritance and interface inheritance. C++ 
 makes no distiction between the two, but C++ programmers make a 
 distinction by referring to interface classes as 'pure virtual'. The 
 Java designers decided that multiple inheritance is a Really Bad Thing 
 when you inherit the implementation, but is acceptable when inheriting 
 the interface. So the 'interface' type was created to enforce the 
 distinction between interface inheritance and implementation 
 inheritance. If you equate an 'interface' with a 'pure virtual' C++ 
 class, you should start to see why D interfaces appear broken in some 
 regards.

This is exactly what I was thinking! Thanks Mike. Maybe Walter thinks that supporting Java-style interfaces is a performance issue. I can't come up with many "good" ways to "emulate" multiple inheritance in D without using interfaces the way Java does. Here's an example: interface ComponentModel { void method(); } abstract class VisualComponent { void draw { blaah } } // just a data structure, not visual class Implementation1: ComponentModel { override void method { blaah blaah } } // used in a gui class Implementation2: VisualComponent, ComponentModel { private: ComponentModel cm; this() { cm = new Implementation1(); } void method() { cm.method(); } } Now, I can use handy abstract arrays like these: ComponentModel[] a; a ~= new Implementation2(); a ~= new Implementation3(); ... a.sort(); findElement(a);
Sep 30 2005
parent Xenon <Xenon_member pathlink.com> writes:
In article <dhjcar$1h14$1 digitaldaemon.com>,
=?ISO-8859-1?Q?Jari-Matti_M=E4kel=E4?= says...
This is exactly what I was thinking! Thanks Mike. Maybe Walter thinks 
that supporting Java-style interfaces is a performance issue.

As I said before, if interfaces are not supported as key types *by intention*, the compiler is supposed to reject my program. Currently I use the following workaround: I define my array as int[Object], and use cast(Object) on insertion and cast(A) on extraction of a key. This is ugly and a bit error-prone, but otherwise works reasonably well. I don't see why the compiler couldn't do something similar automatically, but then I have no idea of DMD's internals. The current situation however, which is silently producing code that is garbage, is IMO worse than no support at all.
Sep 30 2005