Re: storage for temporaries



Lawrence Kirby <lknews@xxxxxxxxxxxxxxx> wrote:
> On Thu, 21 Jul 2005 09:30:04 +0000, S.Tobias wrote:

>> 1. It is obvious that for some large temporary data a compiler
>> must sometimes reserve some memory. What does the Standard
>> say about storage for temporary values?
>
> Very little. However 6.5.2.2p5 says:
>
> "... If an attempt is made to modify the result of a function call or to
> access it after the next sequence point, the behavior is undefined."
>
> Which means that this "temporary storage" doesn't have to last beyond the
> next sequence point. That implies that a pointer to it becomes
> indeterminate after the next sequence point.
>
>> Is it defined (C&V), undefined or unspecified?
>
> The implication is that it can be accessed up to the next sequence point.

I agree it sort of suggests that the function return (and other
rvalues as well: "?:", ",") may "modifiable", but it isn't yet
a (strong) guarantee that there is an object (it says about
an _attempt_ to modify an rvalue, it doesn't mean yet that rvalues
may be modified or may designate objects at all).

> C never says how memory is allocated, the concepts of undefined behaviour
> etc. relate to specific code and constructs not allocation techniques.

What I meant is whether the semantics for the expressions were
defined/undefined/unspecified, not behaviour (although it affects
it in the end as well).

>> What does the Standard say about
>> the output from my program?
>
> There is a squence point after the evaluation of printf()'s argumets just
> before it is called. So the value of the pointer you pass is indeterminate
> within printf() so the behaviour is undefined.

I agree (if at all we can talk about an rvalue object - see below).

But this is easily fixed in two ways:

#define PRINT(msg, ptr) printf("%s: \t%lld\n", msg, (long long)(void*)(ptr))
^^^^^^^^^^^
and then the behaviour is partly implementation defined, and we may
ask about the printed values, or at least whether the Standard guarantees
them to be equal (for the pairs printed in my program).

Or I might modify the program and test expressions like this:
s.a == (0,s).a
and the question is "What does the Standard guarantee about its result?".

(I won't change and post a new version of my program now, but I'll
have above in mind. To have a working version, let's assume PRINT
macro was changed.)

>> 2. Is the expression `f().a[0]' valid? Value of the result of
>> function call (or any other operator that yields an rvalue) is
>> accessed, but there's no sequence point, so there doesn't seem to
>> be an explicit UB in that area. OTOH it is undefined behaviour if
>> the pointer (f().a + 0) has invalid value (6.5.3.2p4). Even if for
>> some reason it is valid and there's no object, then it is undefined
>> behaviour if the lvalue `f().a[0]' does not designate an object when
>> evaluated (6.3.2.1p1). Anyway, it seems like the answer depends
>> on whether the temporary thingy for the rvalue is an object or not.
>
> 6.3.2.1p3 certainly suggests that the f().a part of f().a[0] evaluates to
> a pointer to the first element of an array object.

Now I'm not sure there is an object (storage) at all (in the abstract
machine). The Standard should _first_ state that there is a guaranteed
object there. I think that clause maybe also read as: Since there is no
storage, `f().a' is converted to a pointer which does not point to any
object; or: Since there is no storage, it is undefined to what `f().a'
is converted and thus invokes UB; it doesn't actually say there that
every array expression has a corresponding object.

6.2.4 defines three kinds of storage and defines when it is reserved.
[Note to others: There are significant changes between n869.txt and
the Standard in that part.]
All points of this clause have one thing in common: they describe
declarations of identifiers. In other places of the Standard storage
is defined for unnamed objects (eg. compound literals). Nowhere could
I find a description that could fit temporary thingies under discussion.


Some other thoughts of mine (not necessarily consistent with what
I have written above):

6.2.4p2:
# [...] The value of a pointer becomes indeterminate when
# the object it points to reaches the end of its lifetime.
This roughly means: "object, pointer, no-object, pointer becomes
indeterminate". Since/if there has never been any underlying object
for rvalue expression, the value `f().a' need not be necessarily
indeterminate (but the problem to what it is converted remains).
(Same logic for: void *p = (void*)1234; )

Suppose:
struct s { int a[2]; int m; }
^^^
If there is an underlying object (for the rvalue), would it mean
that this expression is valid?
( (struct s)(void*)(0,s).a )->m;
Above I circumvented the constraint that the operand for "&" must
be an lvalue, ie. this would be wrong:
(&(0,s))->m; //CV
although, if it were right, it would mean exactly the same thing.
(IOW: If a struct rvalue contains an array, it means that
the whole struct rvalue must have a corresponding object.)

Even if 6.3.2.1p3 is to imply that some storage has to be created,
it says only about its "initial element"; it doesn't strictly
imply that storage has to be reserved for other elements. While:
f().a[0];
might be fine, this might not be:
f().a[1];

--
Stan Tobias
mailx `echo siXtY@xxxxxxxxxxxxxxxxxxxxxxxxxx | sed s/[[:upper:]]//g`
.



Relevant Pages

  • Re: Does true ^ true return false?
    ... and i think it's clear from the standard. ... An rvalue of arithmetic, enumeration, pointer, or pointer to member type ...
    (comp.lang.cpp)
  • Re: ...malloc ...from Rome :-)
    ... > Accessing of indeterminate values is undefined behaviour. ... Perhaps you should spend the money on a copy of the real standard. ... > storage is reserved, an object has a constant address. ... sentence of paragraph 2 of 6.2.4 does say "The value of a pointer ...
    (comp.lang.c)
  • Re: reading a declaration
    ... and semantics to a pointer that is implicitly dereferenced, ... There are others who occasionally explain references as being related ... instead of how it is done in the standard? ... and occupies storage. ...
    (comp.lang.cpp)
  • Re: gcc: pointer to array
    ... >>> fits the C99 definition of an Lvalue which does not refer ... of the relevant parts of) the standard, ... This "being found in storage" can be equated to taking the address of the ... Specifies that a decayed array is an rvalue, ...
    (comp.lang.c)
  • Re: Threading problem
    ... Your analysis about the storage being freed is the ... but if this is a pointer to free storage on the ... now you can set it up so that it disables all controls (e.g., ... LRESULT CMyForm::OnThreadDone ...
    (microsoft.public.vc.mfc)