The machine stack and the C language

K

Kelsey Bjarnason

[snips]

Yes it does

int fn(void)
{
int a = 6;
}

int main(void)
{
a = 78;

fn();
}

fixing that somewhat:

void fn(void)
{
int a = 6;
}

int main(void)
{
int a = 78;
fn();
return 0;
}

Before the call to fn() the value of "a" is 78.
During the call to fn it is 6.

Not as written. Before the call to fn, _a variable's_ value is 78.
During the call to fn, _another variable's_ value is 6. A hypothetical
compiler could do the job thusly (intermediate code stage):


..fn
fn_a = 6
jump reg_r

..main
main_a = 78
reg_r = @end
jump @fn

..end
...

The compiler creates two entirely different variables - fn_a and main_a -
then stores a "return address" in a register and does an absolute jump to
fn, followed by an absolute jump to the address in reg_r - the return.

Different contexts, different variables, different functions, call and
return - and not a stack needed anywhere.

Not sure what the example was supposed to prove, but if it was anything
relevant to the requirement of a LIFO structure, it failed.
 
R

Richard Bos

Paul Hsieh said:
They don't? Since when do newbies know about hardware machine
implementations, but not basic data structures?

Since they (and probably their teacher, as well) have read "C for
absolute nitwits in 60 easy minutes", which assumes that all the world's
a Windows boxlet.

Richard
 
M

Malcolm McLean

Kenneth Brody said:
But, the Declaration of Independence dereferences the value "Creator"
without first initializing it, thereby invoking UB. It also makes
reference to the incomplete struct "unalienableRights"[1].


[1] Or would that be an enum?
Enum.
The articles of federation were quite clearly a struct and not, as claimed,
a union.
It is also a rather lousy program. Since the output is "self-evident" a
decent compiler should optimise to a single call to stdout.
 
K

Kenneth Brody

Malcolm said:
Kenneth Brody said:
But, the Declaration of Independence dereferences the value "Creator"
without first initializing it, thereby invoking UB. It also makes
reference to the incomplete struct "unalienableRights"[1].


[1] Or would that be an enum?
Enum.
The articles of federation were quite clearly a struct and not, as claimed,
a union.

I believe it was the Constitution that created the union. (Or, at
least, improve upon a previous, yet unreferenced, version of said
union.)
It is also a rather lousy program. Since the output is "self-evident" a
decent compiler should optimise to a single call to stdout.

Only the definition of "struct truths" is "self-evident". The output
of the program, which includes dumping the contents of the causes[]
array, includes additional data.

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:[email protected]>
 
M

Malcolm McLean

Kenneth Brody said:
I believe it was the Constitution that created the union. (Or, at
least, improve upon a previous, yet unreferenced, version of said
union.)
No.The articles of federation determine which entities are in the United
States of America and which are outside, not the constitution.

States don't share the same territory, so in C terms the USA is clearly a
structure rather than a union.
 
R

Richard Bos

Kenneth Brody said:
Malcolm said:
It is also a rather lousy program. Since the output is "self-evident" a
decent compiler should optimise to a single call to stdout.

Only the definition of "struct truths" is "self-evident". The output
of the program, which includes dumping the contents of the causes[]
array, includes additional data.

And in any case, the run-time behaviour of the resulting object has
proved to be undefined.

Richard
 
R

Richard Bos

Flash Gordon said:
So if all implementations use a stack do you therefore accept that all
implementations are relevant to a thread about stack exhaustion? This is
a serious question because people have pointed out implementations which
have something that you would describe as a stack (based on the above)
but where the stack (if it is one) is not stored linearly.

Partly for that reason, I would say that it is not relevant, and indeed
not on-topic here. The _abstract_ call stack which ISO C (and indeed any
halfway interesting programming language) necessitates cannot be
exhausted, simply because it is an abstract entity.

Any actual machine stack which _may_, but need not, be used to implement
that stack is entirely system-specific (and in fact stack clashes may
have different effects on different machines; I've seen one which
crashed and one which simply overwrote whatever (IIRC malloc()-ated)
memory which happened to be in the stack's way; I can think of others,
but haven't exhausted any more stacks myself). Its discussion is just as
off-topic here, and for the same reason, as the termination of a program
on my Sun Sparc, when I press Stop-A.
Also, what about an implementation that uses two stacks, one for return
addresses and a separate stack for automatic variables?

IIRC I've seen that, once, for the implementation of another language.
Sorry, don't remember where.

Richard
 
K

Kenneth Brody

Richard said:
Kenneth Brody said:
Malcolm said:
It is also a rather lousy program. Since the output is "self-evident" a
decent compiler should optimise to a single call to stdout.

Only the definition of "struct truths" is "self-evident". The output
of the program, which includes dumping the contents of the causes[]
array, includes additional data.

And in any case, the run-time behaviour of the resulting object has
proved to be undefined.

Only because there appears to be a flaw in the Q&A process, and the
current <executive/*.h> source tree appears to have some defects
which slipped into the current patch release. Hopefully, the next
patch will be able to correct the major issues.

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:[email protected]>
 
C

CBFalconer

Richard said:
.... snip ...


IIRC I've seen that, once, for the implementation of another
language. Sorry, don't remember where.

Try Forth, for a language. Try a PIC for hardware.
 
D

David Thompson

Many *processors* do not have stack pointers. S/360, most RISCs,
etc. That the local ABI often assigns a general purpose register for
such a task, is another matter. R13 on S/360, for example. <snip>
Concur.

Many processors, again, S/360, most of the RISCs, implement calls by
saving the return address in a register, often a general purpose
register. The local ABI usually includes saving that in the current
activation record before issuing another call (and often that's
omitted in leaf functions). Again the ABI typically defines what
register gets used for the subroutine return address. On S/360 for
example, it's R15.

Small correction: S/360 convention is R14 for return address and R15
for _callee_ address, which the callee usually needs and uses to
access its pure data aka constants:

L R15, =A(foo)
BALR R14, R15 ; save (updated) 'PC' in R14, jump to R15
; continue

foo
USING foo, R15 ; pseudoop: tell asm R15 contains addressof FOO
L R0, magic ; assembles as (offset=magic-foo)(indexedbyR15)
BR R14 ; jump to R14 = back just after call
magic DC D'42' ; data: answer to life etc.

; actual S/360 assembler(s) don't (or didn't?) use ; for comment
; but added here for clarity

Hence the name of the (in?)famous 'no-op' program often used in JCL
where a program step is needed to attach various DD options to,
IEFBR14 -- program only does BR 14, with a success (0) returncode.
Like /bin/true on Unix-ish, for shells that don't have it builtin.

- formerly david.thompson1 || achar(64) || worldnet.att.net
 
K

Keith Thompson

David Thompson said:
Hence the name of the (in?)famous 'no-op' program often used in JCL
where a program step is needed to attach various DD options to,
IEFBR14 -- program only does BR 14, with a success (0) returncode.
Like /bin/true on Unix-ish, for shells that don't have it builtin.

A program that does nothing -- and that, for many years, did it
incorrectly. (Google "IEFBR14 bug" for details.)

Have I mentioned lately that all software has bugs?
 
H

Harald van Dijk

A program that does nothing -- and that, for many years, did it
incorrectly. (Google "IEFBR14 bug" for details.)

A program that does nothing -- and that, for many years, has done it
incorrectly with no sign of changing: GNU coreutils's version of
/bin/true checks the command-line arguments for --help and --version,
while it is required by various standards to do nothing and ignore the
command-line arguments.

A conforming implementation of the 'true' utility is as short as:
int main(void) { return 0; }
yet even when the program is written in C rather than assembly, it still
ends up with bugs.
 
R

Randy Howard

A program that does nothing -- and that, for many years, has done it
incorrectly with no sign of changing: GNU coreutils's version of
/bin/true checks the command-line arguments for --help and --version,
while it is required by various standards to do nothing and ignore the
command-line arguments.

A conforming implementation of the 'true' utility is as short as:
int main(void) { return 0; }
yet even when the program is written in C rather than assembly, it still
ends up with bugs.

it's an unwritten rule that all GNU software has to include
getopt_long(), even if it doesn't make sense to do so. :)
 
K

Keith Thompson

Harald van Dijk said:
A program that does nothing -- and that, for many years, has done it
incorrectly with no sign of changing: GNU coreutils's version of
/bin/true checks the command-line arguments for --help and --version,
while it is required by various standards to do nothing and ignore the
command-line arguments.

I don't know that I'd call it a bug unless the documentation actually
claims that it conforms to one or more of those standards.

Quoting the documentation:

By default, `true' honors the `--help' and `--version' options.
However, that is contrary to POSIX, so when the environment
variable `POSIXLY_CORRECT' is set, `true' ignores _all_ command
line arguments, including `--help' and `--version'.

Whether it's acceptable to conform to POSIX only when POSIXLY_CORRECT
is set might be an interesting question for another newsgroup.
A conforming implementation of the 'true' utility is as short as:
int main(void) { return 0; }
yet even when the program is written in C rather than assembly, it still
ends up with bugs.

The moral (submoral?) of the story is that it's not always obvious
whether a program has a bug; you have to establish what the
requirements are before you can determine whether the program
satisfies them.
 
R

Randy Howard

The moral (submoral?) of the story is that it's not always obvious
whether a program has a bug; you have to establish what the
requirements are before you can determine whether the program
satisfies them.

Which brings up the old saying, "there are no bugs, there are only
undocumented features."
 
R

Richard Tobin

Keith Thompson said:
However, that is contrary to POSIX, so when the environment
variable `POSIXLY_CORRECT' is set, `true' ignores _all_ command
line arguments, including `--help' and `--version'.

This environment variable used to be called POSIX_ME_HARDER.

-- Richard
 
H

Harald van Dijk

Harald van Dijk said:
A program that does nothing -- and that, for many years, has done it
incorrectly with no sign of changing: GNU coreutils's version of
/bin/true checks the command-line arguments for --help and --version,
while it is required by various standards to do nothing and ignore the
command-line arguments.
[...]
The moral (submoral?) of the story is that it's not always obvious
whether a program has a bug; you have to establish what the requirements
are before you can determine whether the program satisfies them.

Fair enough. It's an unnecessary incompatibility with a standard that GNU
aims to conform to where it makes sense for them to do so, but as it's an
intentional incompatibility, it's not really a bug, it's at worst a
design flaw.
 
R

robertwessel2

Small correction: S/360 convention is R14 for return address and R15
for _callee_ address, which the callee usually needs and uses to
access its pure data aka constants:

L R15, =A(foo)
BALR R14, R15 ; save (updated) 'PC' in R14, jump to R15
; continue

foo
USING foo, R15 ; pseudoop: tell asm R15 contains addressof FOO
L R0, magic ; assembles as (offset=magic-foo)(indexedbyR15)
BR R14 ; jump to R14 = back just after call
magic DC D'42' ; data: answer to life etc.


Indeed. Typo on my part. I've written "BALR R14,R15" (and "BR R15")
thousands of times over the years. Great time for a brain fade...
 
K

Keith Thompson

Harald van Dijk said:
Harald van Dijk said:
A program that does nothing -- and that, for many years, has done it
incorrectly with no sign of changing: GNU coreutils's version of
/bin/true checks the command-line arguments for --help and --version,
while it is required by various standards to do nothing and ignore the
command-line arguments.
[...]
The moral (submoral?) of the story is that it's not always obvious
whether a program has a bug; you have to establish what the requirements
are before you can determine whether the program satisfies them.

Fair enough. It's an unnecessary incompatibility with a standard that GNU
aims to conform to where it makes sense for them to do so, but as it's an
intentional incompatibility, it's not really a bug, it's at worst a
design flaw.

And it's not a serious bug, IMHO. If it were a violation of a
standard that they claim to fully comply with, I'd complain, even if
it were unlikely to matter in practice. But the only reason to
execute "/bin/true --version" with the expectation of having it do
nothing is deliberate conformance testing. There's no real-world
reason to give it an argument at all.

Implementation-level violations of the C standard, on the other hand,
are (I suspect) generally more likely to result in real problems,
though I have no firm basis for this opinion.
 

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,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top