October 27, 2005
Sean Kelly wrote:
> In article <djrbo0$lkk$1@digitaldaemon.com>, Ivan Senji says...
> 
>>With stack based class objects we are getting big bunch of problems with returning destructed objects. Is it really a good idea to have stack-based classes? We have lived without them for a long time in D.
>>And although i can see that they have some advantages (like speed) but it looks to me they bring big problems to the language.
> 
> 
> I very much agree.  But as Walter said, there is a certain class of problems
> that require stack-based behavior to be easily solvable.  I think a careful,
> explicit use of handles might resolve this in some instances, but as Regan's
> smart pointer example shows, this is not particularly natural in D and is very
> prone to programmer error.  I believe there must be a more elegant way to
> implement value semantics than how they are handled in C++, perhaps this is
> mostly a matter of finding it.
> 

And we know just the man to find them :)

> 
> Sean
> 
> 
October 27, 2005
In article <djpppq$12v6$1@digitaldaemon.com>, Sean Kelly says...
>
>In article <djp8g4$fj9$1@digitaldaemon.com>, John Reimer says...
>>
>>I tried that already and numerous other combinations.  Nothing worked.
>>
>>Did you actually get that to work?
>
>I didn't try it.  I know that 'static' is supposed to make local delegates into nonlocal functions and figured it was worth a shot.  I'll try to find some time to mess with it tomorrow.
>
>Sean
>
>

Um actually, you are correct.  The problem arose elsewhere.  Static is required and makes complete sense; it just won't work in the context I gave.

The reason it won't work is because I was silly enough to try to access the init() functions stack variable from within the nested func1.  Clearly, that stack variable fc will only last the life of the init function.  Once that's run the nested function won't be accessing a vaild variable making func1 completely illegal to submit as a callback.  Therefore adding static would work only if I don't try to access the init() variables.

I'm afraid I was not thinking.  My original idea was to encase an external function of normal D linkage (perhaps even a delegate) within a windows linkage callback that could be submitted to win32 function.  My method obviously was invalid.

In conclusion, adding static does the trick for func1() as long as init() stack
variables aren't referenced.

-JJR


October 27, 2005
On Thu, 27 Oct 2005 19:48:41 +0000 (UTC), Sean Kelly <sean@f4.ca> wrote:
> In article <djr50f$4pr$3@digitaldaemon.com>, Walter Bright says...
>>
>> The statement will remain true, and that's because class declarations are
>> only for *references* to a class, not instances. The auto reference will
>> always go away at the end of the scope. Whether the instance does or not
>> depends on if it is on the class or the stack. The way the initializer is
>> written determines if it is a stack or a heap instance.
>
> Interesting.  So the variable would be declared the same either way?  Would such
> a design support returning classes by value?  ie.
>
> MyClass getInstance() {
> MyClass c = MyClass();
> return c;
> }
>
> From what you're saying, this sounds like it would produce undefined behavior.

Why can't this simply be detected at compile time?

Regan
October 27, 2005
Regan Heath wrote:
> On Thu, 27 Oct 2005 19:48:41 +0000 (UTC), Sean Kelly <sean@f4.ca> wrote:
> 
>> In article <djr50f$4pr$3@digitaldaemon.com>, Walter Bright says...
>>
>>>
>>> The statement will remain true, and that's because class declarations  are
>>> only for *references* to a class, not instances. The auto reference will
>>> always go away at the end of the scope. Whether the instance does or not
>>> depends on if it is on the class or the stack. The way the initializer  is
>>> written determines if it is a stack or a heap instance.
>>
>>
>> Interesting.  So the variable would be declared the same either way?   Would such
>> a design support returning classes by value?  ie.
>>
>> MyClass getInstance() {
>> MyClass c = MyClass();
>> return c;
>> }
>>
>> From what you're saying, this sounds like it would produce undefined  behavior.
> 
> 
> Why can't this simply be detected at compile time?
> 

The simple example can allways be complicated:

MyClass getInstance() {
MyClass c = MyClass();
...a lot of code
MyClass a = c;
...a lot of code
return a;
}

I don't think it would be possible for the compiler to track all that is going on with references to stack allocated objects.
What if you had in the method above:

MyClass c = MyClass();
...a lot of code
MyClass a;
if(somecondition)
{
  a = c;
}
else
{
  a = new MyClass();
}
return a;

In this case the code is sometimes legal and sometimes not. No easy solution in sight.

> Regan
October 27, 2005
In article <opszbo89dr23k2f5@nrage.netwin.co.nz>, Regan Heath says...
>
>On Thu, 27 Oct 2005 19:48:41 +0000 (UTC), Sean Kelly <sean@f4.ca> wrote:
>>
>> Interesting.  So the variable would be declared the same either way?
>> Would such
>> a design support returning classes by value?  ie.
>>
>> MyClass getInstance() {
>> MyClass c = MyClass();
>> return c;
>> }
>>
>> From what you're saying, this sounds like it would produce undefined behavior.
>
>Why can't this simply be detected at compile time?

I think it could be for simple cases, but I'm not sure the compiler could catch all such errors.  Though perhaps partial detection is sufficient...


Sean


October 27, 2005
On Thu, 27 Oct 2005 21:30:12 +0000 (UTC), Sean Kelly <sean@f4.ca> wrote:
> In article <opszbo89dr23k2f5@nrage.netwin.co.nz>, Regan Heath says...
>>
>> On Thu, 27 Oct 2005 19:48:41 +0000 (UTC), Sean Kelly <sean@f4.ca> wrote:
>>>
>>> Interesting.  So the variable would be declared the same either way?
>>> Would such
>>> a design support returning classes by value?  ie.
>>>
>>> MyClass getInstance() {
>>> MyClass c = MyClass();
>>> return c;
>>> }
>>>
>>> From what you're saying, this sounds like it would produce undefined
>>> behavior.
>>
>> Why can't this simply be detected at compile time?
>
> I think it could be for simple cases, but I'm not sure the compiler could catch all such errors.  Though perhaps partial detection is sufficient...

Why not? Surely you just flag the actual instance as stack based and then error whenever someone returns a reference to a stack based instance?

Regan
October 27, 2005
On Thu, 27 Oct 2005 23:24:42 +0200, Ivan Senji <ivan.senji_REMOVE_@_THIS__gmail.com> wrote:
> Regan Heath wrote:
>> On Thu, 27 Oct 2005 19:48:41 +0000 (UTC), Sean Kelly <sean@f4.ca> wrote:
>>
>>> In article <djr50f$4pr$3@digitaldaemon.com>, Walter Bright says...
>>>
>>>>
>>>> The statement will remain true, and that's because class declarations  are
>>>> only for *references* to a class, not instances. The auto reference will
>>>> always go away at the end of the scope. Whether the instance does or not
>>>> depends on if it is on the class or the stack. The way the initializer  is
>>>> written determines if it is a stack or a heap instance.
>>>
>>>
>>> Interesting.  So the variable would be declared the same either way?   Would such
>>> a design support returning classes by value?  ie.
>>>
>>> MyClass getInstance() {
>>> MyClass c = MyClass();
>>> return c;
>>> }
>>>
>>> From what you're saying, this sounds like it would produce undefined  behavior.
>>   Why can't this simply be detected at compile time?
>>
>
> The simple example can allways be complicated:
>
> MyClass getInstance() {
> MyClass c = MyClass();
> ...a lot of code
> MyClass a = c;
> ...a lot of code
> return a;
> }
>
> I don't think it would be possible for the compiler to track all that is going on with references to stack allocated objects.
> What if you had in the method above:
>
> MyClass c = MyClass();
> ...a lot of code
> MyClass a;
> if(somecondition)
> {
>    a = c;
> }
> else
> {
>    a = new MyClass();
> }
> return a;
>
> In this case the code is sometimes legal and sometimes not. No easy solution in sight.

If the actual instance is flagged as being stack based then you simply error when a reference is returned that references a stack based instance. You don't actually need to track anything, except that the instance itself is stack based, which you have to track anyway because you're going to destroy it at the end of scope, right?

Regan
October 27, 2005
In article <opszbqebii23k2f5@nrage.netwin.co.nz>, Regan Heath says...
>
>If the actual instance is flagged as being stack based then you simply error when a reference is returned that references a stack based instance. You don't actually need to track anything, except that the instance itself is stack based, which you have to track anyway because you're going to destroy it at the end of scope, right?

If it's on the stack, no explicit tracking is needed.  It will be destroyed automatically as a part of the stack unwinding process when the function exits. Though if the class has a dtor then some tracking is indeed necessary.  Either way, this is something that happens at run time, not compile time.  Though I suppose an AssertError is better than attempting to access released memory.


Sean


October 27, 2005
On Thu, 27 Oct 2005 22:13:02 +0000 (UTC), Sean Kelly <sean@f4.ca> wrote:
> In article <opszbqebii23k2f5@nrage.netwin.co.nz>, Regan Heath says...
>>
>> If the actual instance is flagged as being stack based then you simply
>> error when a reference is returned that references a stack based instance.
>> You don't actually need to track anything, except that the instance itself
>> is stack based, which you have to track anyway because you're going to
>> destroy it at the end of scope, right?
>
> If it's on the stack, no explicit tracking is needed.  It will be destroyed
> automatically as a part of the stack unwinding process when the function exits.
> Though if the class has a dtor then some tracking is indeed necessary.  Either
> way, this is something that happens at run time, not compile time.

So the compiler can't flag a reference as referencing a local stack object at compile time, and error if it's returned? It would have to copy the flag on assignments and so on, but it's _possible_ right?

It's more work for the compiler, but at least it's done at compile time and not runtime.

> Though I
> suppose an AssertError is better than attempting to access released memory.

Most things are.

Regan
October 28, 2005
"Sean Kelly" <sean@f4.ca> wrote in message news:djraup$jeb$1@digitaldaemon.com...
> In article <djr50f$4pr$3@digitaldaemon.com>, Walter Bright says...
> >
> >The statement will remain true, and that's because class declarations are only for *references* to a class, not instances. The auto reference will always go away at the end of the scope. Whether the instance does or not depends on if it is on the class or the stack. The way the initializer is written determines if it is a stack or a heap instance.
>
> Interesting.  So the variable would be declared the same either way?
Would such
> a design support returning classes by value?  ie.
>
> MyClass getInstance() {
> MyClass c = MyClass();
> return c;
> }

Returning references to stack variables is wrong, wrong, wrong <g>.

> From what you're saying, this sounds like it would produce undefined
behavior.
> And in large function calls, this could be an easy mistake to make.  Why
omit
> the need for pointer semantics for heap-based classes?  I'd think it would
offer
> a degree of checking that the handle-based syntax doesn't:
>
> MyClass* getInstance() {
> MyClass c = MyClass();
> return c; // error: cannot convert MyClass to MyClass*
> }

It's not an improvement, the same errors are possible. Those errors are just as possible in C++, too.