public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
* Re: Statement expressions problem returning arrays.
@ 2008-05-29 10:09 Jamax
  0 siblings, 0 replies; 4+ messages in thread
From: Jamax @ 2008-05-29 10:09 UTC (permalink / raw)
  To: Andrew Haley; +Cc: gcc-help



Andrew Haley wrote:
>Jamax wrote:
>> Andrew Haley wrote:
>>> Jamax wrote:
>>>> struct copy { char buf[128]; };
>>>> #define copyof(str) &({ struct copy cp; strcpy(cp.buf, str); cp; }).buf[0]
>>> Don't do that: you'll be using buf outside its scope.  The scope of
>>> buf ends at the end of the block in which it is declared.
>
>gcc treats it like
>
>char *p
>{
>  struct copy cp;
>  strcpy(cp.buf, str);
>  p = cp.buf;
>}

Ok, I understand now.  And I kind of put words in your mouth with the quoted example above due to editing and poor proofreading.  So there is actually nothing wrong with the following expression itself:

&({ struct copy cp; strcpy(cp.buf, str); cp; }).buf[0]

... it's just that once the address has been taken the 'returned' struct goes out of scope, and no longer exists so the address is invalid immediately (or never was valid?).  So even if one does:

void function(char *str) { ... }
function( &({ struct copy cp; strcpy(cp.buf, str); cp; }).buf[0] );

The address passed to function is already invalid before the function is called.  But probably the compiler doesn't actually 'deallocate' the space for it until the function returns, which is why this actually does work even though it shouldn't.

Thanks for taking the time to explain this cool feature, btw!

Jam



^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Statement expressions problem returning arrays.
  2008-05-28 17:24 Jamax
@ 2008-05-28 19:43 ` Andrew Haley
  0 siblings, 0 replies; 4+ messages in thread
From: Andrew Haley @ 2008-05-28 19:43 UTC (permalink / raw)
  To: Jamax; +Cc: gcc-help

Jamax wrote:
> Andrew Haley wrote:
>> Redirected to gcc-help.
>
> Ok thanks, I thought gcc-help was for command line options and such.
> I chopped down the quoted text to the case that works in gcc that
> you say is not valid:
>
>> Jamax wrote:
>>> struct copy { char buf[128]; };
>>> #define copyof(str) &({ struct copy cp; strcpy(cp.buf, str); cp; }).buf[0]
>> Don't do that: you'll be using buf outside its scope.  The scope of
>> buf ends at the end of the block in which it is declared.
>
> The page on statement expressions says the "value of the
> subexpression serves as the value of the entire construct".  So
> really it should be evaluating to a copy of buf, a copy of the
> struct, no?  It seems like a structure or an array of a specific
> size could be a value ...

gcc treats it like

char *p
{
  struct copy cp;
  strcpy(cp.buf, str);
  p = cp.buf;
}

> Similar to:
>
> struct timeval epochTime(void) {
>    struct timeval result = { 0, 0 };
>    return result;
> }
>
> ... or is that also invalid ?!

>> None of those is valid.  This is:
>>
>> #define copyof(STR) ({ char *p = malloc (strlen (STR) + 1); strcpy (p, STR); p; })
>
> It seems like alloca should work and not leak memory like that
> (unless in a loop...).

Sure.

Andrew.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Statement expressions problem returning arrays.
@ 2008-05-28 17:24 Jamax
  2008-05-28 19:43 ` Andrew Haley
  0 siblings, 1 reply; 4+ messages in thread
From: Jamax @ 2008-05-28 17:24 UTC (permalink / raw)
  To: Andrew Haley; +Cc: gcc-help

Andrew Haley wrote:
>Redirected to gcc-help.

Ok thanks, I thought gcc-help was for command line options and such.  I chopped down the quoted text to the case that works in gcc that you say is not valid:

>Jamax wrote:
>> struct copy { char buf[128]; };
>> #define copyof(str) &({ struct copy cp; strcpy(cp.buf, str); cp; }).buf[0]
>
>Don't do that: you'll be using buf outside its scope.  The scope of
>buf ends at the end of the block in which it is declared.

The page on statement expressions says the "value of the subexpression serves as the value of the entire construct".  So really it should be evaluating to a copy of buf, a copy of the struct, no?  It seems like a structure or an array of a specific size could be a value ...

Similar to:

struct timeval epochTime(void) {
   struct timeval result = { 0, 0 };
   return result;
}

... or is that also invalid ?!

>None of those is valid.  This is:
>
>#define copyof(STR) ({ char *p = malloc (strlen (STR) + 1); strcpy (p, STR); p; })

It seems like alloca should work and not leak memory like that (unless in a loop...).

Jam

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Statement expressions problem returning arrays.
       [not found] <1919643.1211990835431.JavaMail.root@elwamui-wigeon.atl.sa.earthlink.net>
@ 2008-05-28 16:33 ` Andrew Haley
  0 siblings, 0 replies; 4+ messages in thread
From: Andrew Haley @ 2008-05-28 16:33 UTC (permalink / raw)
  To: Jamax; +Cc: gcc-help

Redirected to gcc-help.

Jamax wrote:

> Hello.  I have some complex statement-expressions that I am having
> trouble with and this seemed like the more technical mailing list.
> I have boiled them down to these small examples:
>
> #1:
>
> #define copyof(str) ({ char buf[sizeof(str)]; strcpy(buf, str); buf; })

Don't do that: you'll be using buf outside its scope.  The scope of
buf ends at the end of the block in which it is declared.

> int main(int argc, char **argv) {
>    printf("%s %s\n", copyof("hello"), copyof("world"));
> }
>
> That produces the output "hello world" when compiled with no
> optimization, but "hello hello" when compiled with -O or greater
> (but not with just the flags enabled by -O).  It was my impression
> that a character array allocated on the stack was kind of like a
> value rather than a pointer (like char arrays are inside a struct),
> so it seems like the statement-expression should be returning a copy
> of the whole array rather than a copy of a pointer to its previous
> location on the stack.
>
> #2
>
> #define copyof(str) ({ char buf[128]; strcpy(buf, str); buf; })

As above.

> int main(int argc, char **argv) {
>    printf("%s %s\n", copyof("hello"), copyof("world"));
> }
>
> That produces "hello hello" no matter what optimization is used.
>
> #3:
>
> struct copy { char buf[128]; };
> #define copyof(str) ({ struct copy cp; strcpy(cp.buf, str); cp; }).buf

As above.

> int main(int argc, char **argv) {
>        printf("%s %s\n", copyof("hello"), copyof("world"));
> }
>
> Memory fault.
>
> #4:
>
> struct copy { char buf[128]; };
> #define copyof(str) ({ struct copy cp; strcpy(cp.buf, str); cp; }).buf

As above.

> int main(int argc, char **argv) {
>        printf("%s %s\n", copyof("hello"), copyof("world"));
> }
>
> That 'correctly' produces "hello world" with any optimization level.
>
> So my question is, are those all the expected behavior (#1 through
> #3 are not valid)?  From my 'ok' knowledge of C and gnu extensions
> it seems like all four should produce "hello world".

None of those is valid.  This is:

#define copyof(STR) ({ char *p = malloc (strlen (STR) + 1); strcpy (p, STR); p; })

Andrew.

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2008-05-28 21:28 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-05-29 10:09 Statement expressions problem returning arrays Jamax
  -- strict thread matches above, loose matches on Subject: below --
2008-05-28 17:24 Jamax
2008-05-28 19:43 ` Andrew Haley
     [not found] <1919643.1211990835431.JavaMail.root@elwamui-wigeon.atl.sa.earthlink.net>
2008-05-28 16:33 ` Andrew Haley

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).