function composition, sequence point, and unsuspected side effects

M

Malcolm McLean

On Fri, 15 Nov 2013 01:29:52 -0800 (PST), Malcolm McLean

Unless the Standard states somewhere that when one uses
multi-threading, all objects become volatile. In such a case sequence
points become meaningless and we no longer have an abstract machine.

In that case, every single operation involving operands would invoke
undefined behaviour.
If you implement threads, you've got to suppose that there is some mechanism
which prevents them stepping over each other's memory accesses. If this
isn't provided, then indeed you can't say anything about the behaviour of
the program.
In the case of overlapping rand() calls, there are two main possibilities,
a read of the high byte, then a write to the low byte by the other thread,
followed a read of the written low byte, or the reverse, leading to two
different results. But the reconstituted word could conceivably form a
trap representation, terminating the program with an error message. So it's
exactly the same as undefined behaviour.
 
8

88888 Dihedral

Greetings,



my question relates to function calls with hidden side effects,

that are used as arguments of another function, particularly

in regard to the two following sections found in the draft



[3.3.2.2 Function calls] "The order of evaluation of the function

designator, the arguments, and subexpressions within the arguments is

unspecified."



[2.1.2.3 Program execution] "... at sequence points, all side effects of

previous evaluations shall be complete and no side effects of subsequent

evaluations shall have taken place."







For the sake of the exposition, let assume the type Pair,

and a function MakePair() returning a Pair:



typedef struct { int first, second; } Pair;



Pair MakePair (int first, int second) {

Pair pair;
// THIS IS AN VAR IN THE PROGRAM
// STACK SPACE!!!
pair.first= first;

pair.second= second;

return pair;
BAD STYLE! DO YOU MEAN RETURN IN
VAL FOR NON-BUILTIN TYPES?
 
J

James Kuyper

// THIS IS AN VAR IN THE PROGRAM
// STACK SPACE!!!

'pair' has automatic storage duration, and what the C standard says
about the lifetime of objects with automatic storage durations makes
allocating them from the stack a popular implementation strategy, though
that is not mandatory.
However, I'm wondering why you're getting so excited about that fact.
Were you under the impression that it violates some constraint, or
renders the behavior undefined for some reason? If so, could you explain
why you think it's a problem?
BAD STYLE! DO YOU MEAN RETURN IN
VAL FOR NON-BUILTIN TYPES?

The relevant constraint is: "A function declarator shall not specify a
return type that is a function type or an array type." Pair is neither a
function type nor an array type; and is therefore does not violate that
constraint - I'm not aware of any other relevant constraint - do you
know of any?
Returning values of struct type has been allowed since at least C89,
nearly a quarter-century ago, though I vaguely remember being surprised
at the time when I first heard about it, so it was probably not allowed
in K&R C. It's a fairly commonplace technique nowadays.
 
R

regis

BAD STYLE! DO YOU MEAN RETURN IN
VAL FOR NON-BUILTIN TYPES?

C99 introduced compound literals that seem to encourage this style.

Pair
MakePair (int first, int second)
{
return (Pair) { .first= first, .second= second };
}
 
8

88888 Dihedral

'pair' has automatic storage duration, and what the C standard says

about the lifetime of objects with automatic storage durations makes

allocating them from the stack a popular implementation strategy, though

that is not mandatory.

However, I'm wondering why you're getting so excited about that fact.

Were you under the impression that it violates some constraint, or

renders the behavior undefined for some reason? If so, could you explain

why you think it's a problem?








The relevant constraint is: "A function declarator shall not specify a

return type that is a function type or an array type." Pair is neither a

function type nor an array type; and is therefore does not violate that

constraint - I'm not aware of any other relevant constraint - do you

know of any?

Returning values of struct type has been allowed since at least C89,

nearly a quarter-century ago, though I vaguely remember being surprised

at the time when I first heard about it, so it was probably not allowed

in K&R C. It's a fairly commonplace technique nowadays.

To write C programs in manny platforms
are basic trainings in the
IT industry.
 
I

Ian Collins

88888 said:
To write C programs in manny platforms
are basic trainings in the
IT industry.

What was wrong with the code you criticised?

Will you ever learn how to post?
 
S

Seebs

If you implement threads, you've got to suppose that there is some mechanism
which prevents them stepping over each other's memory accesses. If this
isn't provided, then indeed you can't say anything about the behaviour of
the program.

In practice, the general answer is "actually, there's no such mechanism,
but you're given the tools to make one if you want to."
In the case of overlapping rand() calls, there are two main possibilities,
a read of the high byte, then a write to the low byte by the other thread,
followed a read of the written low byte, or the reverse, leading to two
different results. But the reconstituted word could conceivably form a
trap representation, terminating the program with an error message. So it's
exactly the same as undefined behaviour.

I think this ignores a large number of possible cases in which internal
structures used by the RNG, but not visible to the user, end up in
inconsistent states. (Although most rand() implementations are pretty
simple.)

-s
 
S

Seebs

To write C programs in manny platforms
are basic trainings in the
IT industry.

So what?

There's nothing wrong with returning an automatic variable of struct
type.

-s
 
N

nick.keighley.zczc


you don't have a link to a C89 definition/draft (I suppose you'd call it C90) do you?. PDF would be nice...
 
J

James Kuyper

Unless I've missed something (which is entirely possible) the code you
object to is perfectly fine C90 code (the feature that you object to
doesn't disprove that, because its a feature fully supported by C90).
C90 is one of the most widely implemented computer languages in the
world - so targeting C90 meets the goal you specify: to "write C
programs [for many] platforms".
I did lousy writing in English when
I saw lousy source codes in C.

I've been having trouble with my news server for a couple of days now,
or I would have responded to your earlier message.

What makes you think this is lousy source code? The feature you seem to
be objecting to has been a part of standard C for as long as there has
been a C standard, and appears to be used correctly, in a reasonably
idiomatic fashion.
 
N

Noob

James said:
I've been having trouble with my news server for a couple of days now,

I haven't been able to post via eternal-september for a while.
It returned NNTP error 220. Does it work better now?
 
K

Keith Thompson

Noob said:
I haven't been able to post via eternal-september for a while.
It returned NNTP error 220. Does it work better now?

I had a problem the other day. If you see this, it's working now.
 
J

James Harris

Noob said:
I haven't been able to post via eternal-september for a while.
It returned NNTP error 220. Does it work better now?

ES had a problem. All OK now. Incidentally, if it's the same as I had I
think the error code was 441 (which doesn't really tell us anything). Code
220 is just for indicating the message.

http://tools.ietf.org/html/rfc3977

James
 
J

James Kuyper

I haven't been able to post via eternal-september for a while.
It returned NNTP error 220. Does it work better now?

I had been using the port 80 server; switching to the port 119 server
was my work-around. If you got it work without having to switch servers,
then my "success" may have simply been a matter of changing something
irrelevant at the same time that the real problem got solved.
 
S

Seebs

I did lousy writing in English when
I saw lousy source codes in C.

It's poetry, but you have not yet offered any example of something wrong
with the source in question. You've made a vague assertion about
portability, but there's nothing obviously non-portable about returning
a struct from a function. Returning the *address of* an automatic variable
is bad style; returning the automatic variable itself is fine.

-s
 
R

regis

It's poetry, but you have not yet offered any example of something wrong
with the source in question. You've made a vague assertion about
portability, but there's nothing obviously non-portable about returning
a struct from a function. Returning the *address of* an automatic variable
is bad style; returning the automatic variable itself is fine.


Broken code with undefined behevior is a bit beyond style issues ;o)
 
S

Seebs

Broken code with undefined behevior is a bit beyond style issues ;o)

I think strictly speaking, it's not undefined behavior to return the
address of an automatic variable, it's just undefined behavior to do
anything at all with that return value, including storing it or comparing
it to anything.

-s
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,756
Messages
2,569,534
Members
45,007
Latest member
OrderFitnessKetoCapsules

Latest Threads

Top