Re: Gotchas for returning values from blocks

2016-06-13 Thread Era Scarecrow via Digitalmars-d-learn

On Monday, 13 June 2016 at 14:16:58 UTC, jmh530 wrote:
So returning a reference to something on the stack is a bad 
idea, but copying the value would be fine.


 This is easy enough to get wrong elsewhere too. I recall having 
an issue with a foreach, until I added a 'ref' to it. Looking at 
the addresses all pointing to the same spot (the temporary) which 
can add curiously subtle bugs, or blatantly obvious ones.


Re: Gotchas for returning values from blocks

2016-06-13 Thread jmh530 via Digitalmars-d-learn

On Monday, 13 June 2016 at 01:41:07 UTC, Mike Parker wrote:


Everything works fine in your example because 'new' always 
allocates on the heap. Anything allocated on the stack is not 
guaranteed to be valid after the scope exits:


struct Foo
{
int baz;
~this() { baz = 1; }
}

void main()
{
import std.stdio : writeln;

Foo* foo;
{
Foo bar = Foo(10);
foo = 
}
//bar is now out of scope
assert(foo.baz == 10);
}

Struct constructors are always run when exiting a scope. More 
importantly, the pointer to bar is only valid until the stack 
address where it lives is overwritten by another stack 
allocation. In this example, there's no chance for that to 
happen before I access it, but it could happen at any time.


So returning a reference to something on the stack is a bad idea, 
but copying the value would be fine.


Re: Gotchas for returning values from blocks

2016-06-12 Thread Mike Parker via Digitalmars-d-learn

On Sunday, 12 June 2016 at 18:24:58 UTC, jmh530 wrote:

garbage collected variable and assign it to it. Everything 
seems to work fine. I'm just not sure if there are any gotchas 
to be aware of.


class Foo
{
int baz = 2;
}

void main()
{
import std.stdio : writeln;

Foo foo;
{
Foo bar = new Foo();
foo = bar;
}
//bar is now out of scope
assert(foo.baz == 2);
}


Everything works fine in your example because 'new' always 
allocates on the heap. Anything allocated on the stack is not 
guaranteed to be valid after the scope exits:


struct Foo
{
int baz;
~this() { baz = 1; }
}

void main()
{
import std.stdio : writeln;

Foo* foo;
{
Foo bar = Foo(10);
foo = 
}
//bar is now out of scope
assert(foo.baz == 10);
}

Struct constructors are always run when exiting a scope. More 
importantly, the pointer to bar is only valid until the stack 
address where it lives is overwritten by another stack 
allocation. In this example, there's no chance for that to happen 
before I access it, but it could happen at any time.


Re: Gotchas for returning values from blocks

2016-06-12 Thread jmh530 via Digitalmars-d-learn

On Sunday, 12 June 2016 at 19:30:49 UTC, Era Scarecrow wrote:

On Sunday, 12 June 2016 at 18:24:58 UTC, jmh530 wrote:

I'm just not sure if there are any gotchas to be aware of.


 Aside from forgetting it's it's own block, you might add a 
return statement to it and leave the entire function. Or forget 
what's in what scope (assuming you do more than 1-2 pages of 
code per function). They do sorta behave like inlined void 
delegate functions (skip the call & heavy stack management).


 Unless there's a good reason for using blocks I don't see the 
need, since you will likely use inner scopes in if statements 
and the like anyways.


Good points. Thanks for the reply.


Re: Gotchas for returning values from blocks

2016-06-12 Thread Era Scarecrow via Digitalmars-d-learn

On Sunday, 12 June 2016 at 18:24:58 UTC, jmh530 wrote:

I'm just not sure if there are any gotchas to be aware of.


 Aside from forgetting it's it's own block, you might add a 
return statement to it and leave the entire function. Or forget 
what's in what scope (assuming you do more than 1-2 pages of code 
per function). They do sorta behave like inlined void delegate 
functions (skip the call & heavy stack management).


 Unless there's a good reason for using blocks I don't see the 
need, since you will likely use inner scopes in if statements and 
the like anyways.