digitalmars.D.bugs - [Issue 1778] New: Can not create pointer to class reference
- d-bugmail puremagic.com (20/20) Jan 10 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1778
- d-bugmail puremagic.com (17/17) Jan 16 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1778
- d-bugmail puremagic.com (59/59) Jan 17 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1778
- d-bugmail puremagic.com (17/17) Jan 17 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1778
- d-bugmail puremagic.com (31/31) Jan 17 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1778
- d-bugmail puremagic.com (8/8) Jan 17 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1778
- d-bugmail puremagic.com (11/11) Jan 17 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1778
- d-bugmail puremagic.com (57/61) Jan 18 2008 Because probably in most cases, when you will need something like pointe...
http://d.puremagic.com/issues/show_bug.cgi?id=1778 Summary: Can not create pointer to class reference Product: D Version: 1.026 Platform: PC OS/Version: All Status: NEW Severity: major Priority: P2 Component: DMD AssignedTo: bugzilla digitalmars.com ReportedBy: aarti interia.pl Below doesn't compile: ---- A* cp = new A*; ---- Type of new A* is (A**) while it should be A*. Reference: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D.learn&article_id=10683 --
Jan 10 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1778 bugzilla digitalmars.com changed: What |Removed |Added ---------------------------------------------------------------------------- Status|NEW |RESOLVED Resolution| |INVALID In general, new T; will return a value of type T*, unless T is a reference type (i.e. a class or an array), in which case it returns a value of type T. Therefore, new T*; will allocate a pointer to T, and return a value which points to that pointer to T. In other words, a T**. This is as designed. --
Jan 16 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1778 aarti interia.pl changed: What |Removed |Added ---------------------------------------------------------------------------- Status|RESOLVED |REOPENED Resolution|INVALID | Well, the problem is not that simple as it seems to be... Currently it is NOT possible to create in sane way pointer to class reference on heap. It affects also all types of form: A**, A***, A**** ...., where A is a class because to initialize them it is necessary at last to initialize A*. Because of pointer is not created, there is no way to initialize such a variable. More comments in below example: import std.stdio; T create(T)() { static if (is(T == class)) return new T; else return *(new T); } class A { void test() {writefln("Ok!");}} struct B {} void main() { //Does not create pointer to A in memory A* x = *(new A*); writefln("x is null: ", x is null); //*x = new A; //access violation, because x is null as only //first pointer is created //How to initialize below variable? A** y = new A*; //*y = ???? //Workaroud 1 A* u = cast(A*) new B; *u = new A; u.test; //Workaround 2 static A ca; ca = new A; u = &ca; //unfortunately in this case there remains memory leak //Workaroud 3 //IMHO best long term solution, but it is difficult for me to predict all //consequences //Allow that typeof(A*) == typeof(A) //and typeof(&A) == typeof(A) //for classes. It will allow also to create one create function for //all types: //T* create(T)() { // return new T; //} //Workaround 4 //When creating (new A*) //initialize not only first pointer //but also second, so that // *(new A*) is not null } --
Jan 17 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1778 bugzilla digitalmars.com changed: What |Removed |Added ---------------------------------------------------------------------------- Status|REOPENED |RESOLVED Resolution| |INVALID C c = new C; C* pc = new C*; *pc = &c; Note that it appears you are asking that: new C*; allocate both a C and a pointer to C as two separate allocations. This is not done for the same reason that: new int*; does only one allocation - not two. --
Jan 17 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1778 Well, your solution is IMHO wrong for most real-life use cases. (And that was my first try to solve problem). BTW your example should look like below (there is an error in your's): C c = new C; C** ppc = new C*; *ppc = &c; And now, let's put this code into function which returns pointer to C: --- import std.stdio; class C {void test() {writefln("Ok");}} C* func() { C c = new C; C** ppc = new C*; *ppc = &c; return *ppc; } void main() {func.test;} --- Something that I don't understand in above code is the fact that it... works! But it should definitely not! Please notice in function func that there is address of local variable taken. After exiting scope this address might be very quickly invalid. Without all this pointer machinery, when you put just return &c; at the end of function you get from compiler: src/quicktest.d(7): Error: escaping reference to local variable c IMHO it works just because of some specific stack access optimization in my/others? computer. Or compiler makes some magic? I don't know why it works, but IMHO this bug should be reopened... --
Jan 17 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1778 1) Why is it wrong for real live cases? 2) You're right, pc should be declared C** 3) The return "worked" because the value still existed, undamaged, on the stack. The stack cleanup just adjusts the ESP, it doesn't actually stomp on the values --
Jan 17 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1778 You can also write: class C { } void test() { C c = new C; C* pc = (new C[1]).ptr; *pc = c; } --
Jan 17 2008
http://d.puremagic.com/issues/show_bug.cgi?id=17781) Why is it wrong for real live cases?Because probably in most cases, when you will need something like pointer to class you will need also to return it from function. And then you have a problem with escaping reference to local variable.3) The return "worked" because the value still existed, undamaged, on the stack. The stack cleanup just adjusts the ESP, it doesn't actually stomp on the valuesWell it confirms that it was just plain luck, that program was working... 4) (answer to your next comment) class C { } void test() { C c = new C; C* pc = (new C[1]).ptr; *pc = c; } It seems to be similar workaround like number 1 from my workaround list? And as I assume it should work when returning from function? ------------- It's nice that there are workarounds which are actually working right now. But IMHO they are still only workarounds (quick hacks). And according to principle "No issue left behind", it should be rather solved than hacked. Maybe you would consider my proposition: *** For A being a class, types A and A* should be implicitly castable between each other. *** Known consequences (probably just iceberg top, but let me start): 1. In index of associative array: if type of index is A* array should be indexed by pointer, if type of index is A, array should be indexed by opHash 2. Proper reductions needs to be applied for types like A**, A*** etc. (see below) ... Advantages: It will reduce number of necessary workarounds in code: 1. In constructor-like functions: instead of currently necessary: T create(T)() { static if (is(T == class)) return new T; else return *(new T); } 2. When storing pointers to class in associative arrays. Currently I have to cast A to (void*) to store into associative array. With new solution I would just declare array index as A* and put class there. 3. It solves cleanly problem of creation pointer to class A** p = new A*; which, after reduction is same as: (A*)* p = new (A*); and A* p = new A; 4. This change is not sophisticated workaround to hide real state of matter, but rather exposes real state of matter which is that new A; creates pointer to class A. Anyway I would say that this bug should stay open, till sane solution will be found. --
Jan 18 2008