three little issues

spir denis.spir at gmail.com
Sun Feb 6 10:40:03 PST 2011


On 02/06/2011 02:13 PM, bearophile wrote:
> Before a D function starts, a stack frame is created. It will contain your stack-allocated struct instance. When the function ends its stack frame is destroyed virtually by moving a stack pointer, so the struct may be overwritten by other things, like by a call to writeln that creates many stack frames. If the stack frame is not overwritten and you save by*value*  the stack contents, you have successfully saved your data in the array of S, but accessing virtually deleted data in the stack is a bad practice to avoid.

Right, I may be successful to store by value as you say, before the frame is 
overwritten, and so-to-say by chance.

But this does not explain why the compiler refuses:
	// 1
	auto s = S(data);
	return &s;
and accepts:
	// 2
	return &(S(data));
or does it?
What are the supposed differences in semantics or behaviour, if any? For 
(naive) me, these 2 pieces of code are exactly synonym (and I would be happy 
with the compiler suppressing s in 1 or instead creating an intermediate var in 
2, whatever it judges better).

I have a third version, in the case where I need to check something in s before 
returning its address:
	// 3
	auto p = &(S(data));
	if ((*p).check())
	    return null;
	return p;
(This is just a synopsis). I need to write it that way, else it's refused. (I 
mean I cannot first have an s var explicitely, check on it directly, then take 
it's address as return value).

Another use case is where S's are in an array, else both the synopsis and the 
solution are analog to the last code above. Since they are struct values, I use 
a pointer to avoid a useless local copy. What do you think of this idiom? Is it 
common? Is it good at all?
Real code:

     /** AST Node constructed from lexeme of type typeCode, if any,
         at current position in lexeme stream --else null.
         Node's constructor must expect the lexeme's slice as (only) input.
     */
     Node node (Node) (string typeCode) if (is(Node == class)) {
         // Avoid useless local copy of lexeme by using pointer
         // (instead of local struct variable).
         Lexeme* pointer = &(this.lexemes[this.cursor]);
         if ((*pointer).typeCode == typeCode) {
             ++ this.cursor;
             return new Node((*pointer).slice);
         }
         return null;
     }

My "spontaneous" version of this code would indeed be:

     Node node (Node) (string typeCode) if (is(Node == class)) {
         Lexeme lexeme = this.lexemes[this.cursor];
         if (lexeme.typeCode == typeCode) {
             ++ this.cursor;
             return new Node(lexeme.slice);
         }
         return null;
     }

The aim is avoiding copying pieces of the (plain text) source when lexing, 
parsing, constructing the AST. If I'm right in analysing my app as of now, I 
have, thank to D's "view" slices, exactly 0 copy from source text to AST. 
Meaning even AST nodes which hold a piece of the source text (strings, symbols, 
maybe more) actually have a view of the very original source. In any other 
language (or is it in my pr2vious coding style?), I would have copied at the 
very minimum once. Even in a dynamic language (which strings are indeed 
ref'ed), to create the first "slice" (in the sense of substring).
Thank you, Walter!

Denis
-- 
_________________
vita es estrany
spir.wikidot.com



More information about the Digitalmars-d-learn mailing list