www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - another compiler bug?

reply Aarti_pl <aarti interia.pl> writes:
How to create pointer to class?

Below doesn't compile:
----
A* cp = new A*;
----
Type of new A* is (A**) while it should be A*.

Any comments? (Maybe I missed something...)

PS. I know that it is possible to create pointer to class in two steps.

BR
Marcin Kuszczak
(aarti_pl)
Jan 09 2008
next sibling parent reply Robert DaSilva <sp.unit.262+digitalmars gmail.com> writes:
Aarti_pl wrote:
 How to create pointer to class?
 
 Below doesn't compile:
 ----
 A* cp = new A*;
 ----
 Type of new A* is (A**) while it should be A*.
 
 Any comments? (Maybe I missed something...)
 
 PS. I know that it is possible to create pointer to class in two steps.
 
 BR
 Marcin Kuszczak
 (aarti_pl)

Because new returns a pointer to what you ask for. The reason new returns A when you ask it for A instead of *A like it would with anything else (anything not a class), is because A is actually a pointer to an instance of class A. The true is this is probably the best behaver, maybe... This raise some important question, I think.
Jan 09 2008
parent Aarti_pl <aarti interia.pl> writes:
Robert DaSilva pisze:
 Aarti_pl wrote:
 How to create pointer to class?

 Below doesn't compile:
 ----
 A* cp = new A*;
 ----
 Type of new A* is (A**) while it should be A*.

 Any comments? (Maybe I missed something...)

 PS. I know that it is possible to create pointer to class in two steps.

 BR
 Marcin Kuszczak
 (aarti_pl)

Because new returns a pointer to what you ask for. The reason new returns A when you ask it for A instead of *A like it would with anything else (anything not a class), is because A is actually a pointer to an instance of class A. The true is this is probably the best behaver, maybe... This raise some important question, I think.

The problem here is that compiler does not return pointer to class reference as it should. That's why the line of code doesn't compile although it should. I don't see why its not possible for compiler to behave correctly. Of course internally compiler should behave differently for classes than for other types. But this is just a consequence of decision that classes should be threated as value types in D. BR Marcin Kuszczak (aarti_pl)
Jan 10 2008
prev sibling parent reply torhu <no spam.invalid> writes:
Aarti_pl wrote:
 How to create pointer to class?
 
 Below doesn't compile:
 ----
 A* cp = new A*;
 ----
 Type of new A* is (A**) while it should be A*.
 
 Any comments? (Maybe I missed something...)
 
 PS. I know that it is possible to create pointer to class in two steps.

Do you actually want to heap allocate a pointer to an object reference? Try this: A* cp = *(new A*); Maybe you really wanted to take the allocate an object, and then get the address of the reference? I guess so, but I don't know if that's possible in a single statement.
Jan 09 2008
parent reply Aarti_pl <aarti interia.pl> writes:
torhu pisze:
 Aarti_pl wrote:
 How to create pointer to class?

 Below doesn't compile:
 ----
 A* cp = new A*;
 ----
 Type of new A* is (A**) while it should be A*.

 Any comments? (Maybe I missed something...)

 PS. I know that it is possible to create pointer to class in two steps.

Do you actually want to heap allocate a pointer to an object reference?

Yes. After writing my post I discovered that 2 stage creation will not work for returning result from function. So my 'PS.' in fact is not solution.
 Try this:
 A* cp = *(new A*);

I needed something like above. Unfortunately your solution doesn't work (don't know why). I get access violation in my program when returning '*(new A*)'. I managed to overcome bug in DMD with below: void func(T)() { static TYPE res; res = new T; return &res; } although it will cause memory leaks for every type for which the function is instantiated. So I consider bug in DMD as quite serious...
 Maybe you really wanted to take the allocate an object, and then get the 
 address of the reference?  I guess so, but I don't know if that's 
 possible in a single statement.

No, it won't work in my program as I must return this pointer from function. Thanks for your post! BR Marcin Kuszczak (aarti_pl)
Jan 10 2008
next sibling parent Aarti_pl <aarti interia.pl> writes:
Aarti_pl pisze:
 torhu pisze:
 Aarti_pl wrote:

 A* cp = *(new A*);

I needed something like above. Unfortunately your solution doesn't work (don't know why). I get access violation in my program when returning '*(new A*)'. I managed to overcome bug in DMD with below: void func(T)() { static TYPE res; res = new T; return &res; } although it will cause memory leaks for every type for which the function is instantiated. So I consider bug in DMD as quite serious...

It can be of course also problem with logic in my program. I will check it. BR Marcin Kuszczak (aarti_pl)
Jan 10 2008
prev sibling next sibling parent reply Christopher Wright <dhasenan gmail.com> writes:
Aarti_pl wrote:
 torhu pisze:
 Aarti_pl wrote:
 How to create pointer to class?

 Below doesn't compile:
 ----
 A* cp = new A*;
 ----
 Type of new A* is (A**) while it should be A*.

 Any comments? (Maybe I missed something...)

 PS. I know that it is possible to create pointer to class in two steps.

Do you actually want to heap allocate a pointer to an object reference?

Yes. After writing my post I discovered that 2 stage creation will not work for returning result from function. So my 'PS.' in fact is not solution. > Try this:
 A* cp = *(new A*);

I needed something like above. Unfortunately your solution doesn't work (don't know why). I get access violation in my program when returning '*(new A*)'. I managed to overcome bug in DMD with below: void func(T)() { static TYPE res; res = new T; return &res; } although it will cause memory leaks for every type for which the function is instantiated. So I consider bug in DMD as quite serious...

Does that work? With more than one instance created? I would think you'd only ever be able to access the most recent one.
Jan 10 2008
parent Aarti_pl <aarti interia.pl> writes:
Christopher Wright pisze:
 I managed to overcome bug in DMD with below:

 void func(T)() {
     static TYPE res;
     res = new T;
         return &res;
 }

 although it will cause memory leaks for every type for which the 
 function is instantiated. So I consider bug in DMD as quite serious...

Does that work? With more than one instance created? I would think you'd only ever be able to access the most recent one.

Yes. I used something similar in C++. BR Marcin Kuszczak (aarti_pl)
Jan 10 2008
prev sibling parent reply Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
Aarti_pl wrote:
 torhu pisze:
 Aarti_pl wrote:


 I managed to overcome bug in DMD with below:
 
 void func(T)() {
     static TYPE res;
     res = new T;
         return &res;
 }
 
 although it will cause memory leaks for every type for which the 
 function is instantiated. So I consider bug in DMD as quite serious...

That will only allocate one reference per type (*not* per call to the function). Try this workaround instead: ----- T* func(T)() { struct helper { T val; } return &(new helper).val; } ----- This heap-allocates a struct containing only a reference and returns a pointer to that member. I don't think it's a bug in the compiler though, it behaves according to the spec. However, this seems to be an oversight in the spec as it doesn't provide for any way to directly allocate a "Class*".
Jan 11 2008
parent reply Aarti_pl <aarti interia.pl> writes:
Frits van Bommel pisze:
 Aarti_pl wrote:
 torhu pisze:
 Aarti_pl wrote:


 I managed to overcome bug in DMD with below:

 void func(T)() {
     static TYPE res;
     res = new T;
         return &res;
 }

 although it will cause memory leaks for every type for which the 
 function is instantiated. So I consider bug in DMD as quite serious...

That will only allocate one reference per type (*not* per call to the function). Try this workaround instead:

That's exactly what I said :-)
 -----
 T* func(T)() {
     struct helper {
         T val;
     }
     return &(new helper).val;
 }
 -----
 This heap-allocates a struct containing only a reference and returns a 
 pointer to that member.

Your solution probably works correctly, as another solution proposed by torhu. Though I will stay with my workaround for now as probably due to logic error in my app these solution also cause seg fault. But for now I can not say precisely why...
 
 I don't think it's a bug in the compiler though, it behaves according to 
 the spec. However, this seems to be an oversight in the spec as it 
 doesn't provide for any way to directly allocate a "Class*".

Can you point me to correct place in spec? IMHO it is a bug, as creating new class does not produce pointer but reference. Well physically it is same thing but it should be obvious what should be created: new Class -- create reference to class -> physically *data new Class* -- create pointer to reference -> physically **data as you see in second example type is exactly same as compiler is complaining about. Probably compiler should just figure out different type from it: instead of Class** it should be just Class*. BR Marcin Kuszczak (aarti_pl)
Jan 11 2008
parent reply Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
Aarti_pl wrote:
 Frits van Bommel pisze:
 Aarti_pl wrote:
 torhu pisze:
 Aarti_pl wrote:


 I managed to overcome bug in DMD with below:

 void func(T)() {
     static TYPE res;
     res = new T;
         return &res;
 }

 although it will cause memory leaks for every type for which the 
 function is instantiated. So I consider bug in DMD as quite serious...

That will only allocate one reference per type (*not* per call to the function). Try this workaround instead:

That's exactly what I said :-)

No, you say it will allocate a reference per instantiation and refer to this as a memory leak (presumably because they're not gc-ed after they're no longer in use). My point was that a second call to the function (for the same type) will overwrite the location returned from the first call.
Jan 12 2008
parent reply Marcin Kuszczak <aarti_please_no spam_interia.pl> writes:
Frits van Bommel wrote:

 although it will cause memory leaks for every type for which the
 function is instantiated. So I consider bug in DMD as quite serious...

That will only allocate one reference per type (*not* per call to the function). Try this workaround instead:

That's exactly what I said :-)

No, you say it will allocate a reference per instantiation and refer to this as a memory leak (presumably because they're not gc-ed after they're no longer in use).

Yes, I probably should say "memory leak" (singular) to express what I meant.
 My point was that a second call to the function (for the same type) will
 overwrite the location returned from the first call.

That leads me to discuss another bug which I discovered. Let's say we have program like below: -------- import std.stdio; struct Pattern(T : bool) { string beg = "test"; } Pattern!(T) get(T)() { static Pattern!(T) pattern; return pattern; } void main() { writefln(get!(bool).beg); get!(bool).beg = "other"; writefln(get!(bool).beg); } -------- Above program prints: test test although I would expect it will print: test other It seems that memory reserved for struct in template function is initialized every time the function is executed. This behaviour is different when we change Pattern to be class instead of struct. Then it is possible to create kind of singleton pattern for every type. What do you think? BTW. Where should I discuss bugs? I have another dozen of them and would like to discuss some of them before posting to bugzilla. Is it better to post to d.learn or d.bugs? -- Regards Marcin Kuszczak (Aarti_pl) ------------------------------------- Ask me why I believe in Jesus - http://www.zapytajmnie.com (en/pl) Doost (port of few Boost libraries) - http://www.dsource.org/projects/doost/ -------------------------------------
Jan 12 2008
parent reply Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
Marcin Kuszczak wrote:
 That leads me to discuss another bug which I discovered. 
 
 Let's say we have program like below:
 --------
 import std.stdio;
 struct Pattern(T : bool) {
     string beg = "test";
 }
 
 Pattern!(T) get(T)() {
     static Pattern!(T) pattern;
     return pattern;
 }
 
 void main() {
     writefln(get!(bool).beg);
     get!(bool).beg = "other";
     writefln(get!(bool).beg);
 }
 --------
 
 Above program prints:
 test
 test
 
 although I would expect it will print:
 test
 other
 
 It seems that memory reserved for struct in template function is initialized
 every time the function is executed.

No, it's just initialized once. However, the struct itself isn't returned; a *copy* of it is returned. That copy is what's modified by the assignment. The second call will return a fresh copy of the original (with "test" remaining the string value).
 This behaviour is different when we change Pattern to be class instead of
 struct. Then it is possible to create kind of singleton pattern for every
 type.

Yes, class instances are passed by reference, so the assignment would change the 'static' instance (assuming you 'new' it the first time around, so there is one). The same effect should be observed if you change the function to: ----- Pattern!(T)* get(T)() { static Pattern!(T) pattern; return &pattern; } ----- for the struct version (returning a pointer to the global instance instead of a copy of it).
 What do you think?
 
 BTW. Where should I discuss bugs? I have another dozen of them and would
 like to discuss some of them before posting to bugzilla. Is it better to
 post to d.learn or d.bugs?

If they are of the same kind as this one, you may want to stick to d.learn as it's not actually a bug :P. (Or at least, it's a bug in your code rather than in the compiler; the compiler does exactly what I'd expect it to do and what IMO it should do)
Jan 13 2008
parent reply Marcin Kuszczak <aarti_please_no spam_interia.pl> writes:
Frits van Bommel wrote:

 No, it's just initialized once. However, the struct itself isn't
 returned; a *copy* of it is returned. That copy is what's modified by
 the assignment. The second call will return a fresh copy of the original
 (with "test" remaining the string value).
 
 This behaviour is different when we change Pattern to be class instead of
 struct. Then it is possible to create kind of singleton pattern for every
 type.

Yes, class instances are passed by reference, so the assignment would change the 'static' instance (assuming you 'new' it the first time around, so there is one). The same effect should be observed if you change the function to: ----- Pattern!(T)* get(T)() { static Pattern!(T) pattern; return &pattern; } ----- for the struct version (returning a pointer to the global instance instead of a copy of it).

Thanks! Now this behaviour is clear for me.
 
 BTW. Where should I discuss bugs? I have another dozen of them and would
 like to discuss some of them before posting to bugzilla. Is it better to
 post to d.learn or d.bugs?

If they are of the same kind as this one, you may want to stick to d.learn as it's not actually a bug :P. (Or at least, it's a bug in your code rather than in the compiler; the compiler does exactly what I'd expect it to do and what IMO it should do)

Some of them probably are bugs, and some of them are not. That's why I prefer to discuss them before posting to bugzilla. -- Regards Marcin Kuszczak (Aarti_pl) ------------------------------------- Ask me why I believe in Jesus - http://www.zapytajmnie.com (en/pl) Doost (port of few Boost libraries) - http://www.dsource.org/projects/doost/ -------------------------------------
Jan 13 2008
parent Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
Marcin Kuszczak wrote:
 Some of them probably are bugs, and some of them are not. That's why I
 prefer to discuss them before posting to bugzilla.

I'd say if you're not sure if they're bugs, best post here first. Then once you're sure something is a bug you can post it to bugzilla. This way, D.bugs doesn't get cluttered with non-bugs.
Jan 14 2008