Crazy stuff

L

Lawrence Kirby

On Mon, 15 Nov 2004 04:09:47 +0000, Dave Thompson wrote:

....
Huh? Unless I completely misunderstand what you are saying:
while the C standard does not specify implementation techniques, and
so can't topically rely on "the stack", on every machine I know of
that has a "processor stack segment", or indeed just a "processor
(memory) stack" anywhere, it was designed to be and in fact is used
for C (and other HLL) function-invocation frames in a stack fashion.


Well, the 6502 processor, which certainly does have C compilers targetting
it, has a 256 byte processor stack. I suspect the C compilers don't use
that to hold automatic variables.

Lawrence
 
D

Dave Vandervies

Huh? Unless I completely misunderstand what you are saying:
while the C standard does not specify implementation techniques, and
so can't topically rely on "the stack", on every machine I know of
that has a "processor stack segment", or indeed just a "processor
(memory) stack" anywhere, it was designed to be and in fact is used
for C (and other HLL) function-invocation frames in a stack fashion.

This is true, but not what I was saying (or at least not what I intended
to say).

The C (and other HLL) function-invocation stack is an abstract thing on
which continuations[1], automatic variables, and possibly a few things I'm
not thinking of live. The fact that, where they exist, hardware-assisted
stack mechanisms are universally used to (and, in fact, designed to)
implement this doesn't mean they're the same thing; one is a construct
of the language being implemented, and one is the back-end mechanism
used to implement it.

Note that (relevant to the subject, but not to your comments if
I'm understanding them correctly) even on systems without such a
hardware-assisted mechanism (I believe older IBM systems are the
canonical example, though I'd probably get the details wrong if I tried
to remember them) the invocation records (implemented as, say, a linked
list of freestore-allocated invocation frames) need to look, feel, and
smell like a stack - this is an obvious example of a function-invocation
stack not being implemented with a hardware stack.


dave

[1] That is, what to do when the function finishes (including what to
do with the return value, if there is one). Typically this is
implemented as a machine address referring to the point in the calling
code immediately after the actual subroutine call, where the return
value is handled appropriately and the rest of the caller continues
to run.
 
C

Charlie Gordon

Malcolm said:
So C defines various terms, but how does it define them? In the Standard,
which is an English-language document. So sometimes C will also define the
words used to define these terms.
See the problem?
Ultimately we have to use terms like "read-only memory", which are not
defined by the C standard, but which have meanings given to them by usage.

If the OP doesn't understand why an attempt to modify a string literal
causes a crash, then its unlikely that he will be familiar with the term
"string literal". He may also be shaky on "undefined behaviour". So a
technically more accurate explanation is in fact more confusing.

I agree 100%
Furthermore, strdup() may not be specified in the Standard, it is defined by
POSIX and is widely available on the systems used by beginners. Its semantics
are easy to understand.
On the contrary, strtok() has always been part of the Standard, but is a
constant cause of misunderstandings and implementation bugs. IMHO programmers
should be instructed to not use this bastard, not its friends (gets, strncpy,
strncat...)

strtok modifies the string pointed to by its first argument (if not NULL) and
keeps a copy to it in a global variable.
passing it a string literal such as "this is a string" may cause undefined
behaviour, such as crash.
passing it a pointer to automatic storage, such as what you do in the example,
is error prone.
initializing a automatic character array with a string literal is inefficient.
strtok() is flawed is ways beyond the understanding of newbie developpers, it
should not be used.

Chqrlie.
 
C

Charlie Gordon

"Endymion Ponsonby-Withermoor III"
OK. I sit corrected.

you pedants are so picky and righteous !

The C standard did not make it const char to avoid breaking countless sloppy
programs with compile time errors...
And more often than not, inconsistent use of char and string literals, hiding
subtile bugs waiting to bite at runtime.
So it is not "const", but if you try to modify it, you get UB ! Its has the
flavor and behaviour, but not the type...
Gimme a break, I'd rather newbies think it *be* const are understand why they
get a crash.

The case of the missing return statement is even a worse hack to accomodate
historical trash. It is about time some of those remnents from the 70s should
be fixed.

Just exactly what prevented the inclusion of strdup() into the Standard eludes
me !

The case against strtok() is also worth fighting : please stop teaching newbies
to use functions with flawed semantics like this one or its friends : gets(),
strncpy(), strncat()...

Chqrlie.
 
R

Richard Bos

Charlie Gordon said:
you pedants are so picky and righteous !

With good reason.
Just exactly what prevented the inclusion of strdup() into the Standard eludes
me !

It's easily emulated and would sit awkwardly in whichever header you put
it in.
The case against strtok() is also worth fighting :

strtok() has its problems, but where it's useful, it's very useful.
please stop teaching newbies to use functions with flawed semantics like
this one or its friends : gets(), strncpy(), strncat()...

Obviously I agree about gets(), and strncpy() is rarely if ever the
right function, but if you won't allow strncat(), which function _do_
you use when you want a length-limited string copy?

Richard
 
C

Charlie Gordon

Hello,
strtok() has its problems, but where it's useful, it's very useful.


Obviously I agree about gets(), and strncpy() is rarely if ever the
right function, but if you won't allow strncat(), which function _do_
you use when you want a length-limited string copy?

Why not write one that does what is needed.

Or use a test and write appropriate code for each case.

strncat() is not the worst of these, but it is consistently misused in code I
come across :

strncpy(dest, source, sizeof(dest)); // dangerous !
strncat(dest, source, sizeof(dest)); // worse even!

Chqrlie.

PS: the glove don't fit, you must acquit !
 
L

Lawrence Kirby

On Tue, 16 Nov 2004 12:36:55 +0100, Charlie Gordon wrote:

....
The case against strtok() is also worth fighting : please stop teaching newbies
to use functions with flawed semantics like this one or its friends : gets(),
strncpy(), strncat()...

What's wrong with strncat()?

Lawrence
 
C

Charlie Gordon

Lawrence Kirby said:
On Tue, 16 Nov 2004 12:36:55 +0100, Charlie Gordon wrote:

...


What's wrong with strncat()?

It is often misunderstood, and misused :

strncpy(dest, source, sizeof(dest)); // dangerous !
strncat(dest, source, sizeof(dest)); // worse even!

Chqrlie.
 
M

Michael Mair

Lawrence said:
On Tue, 16 Nov 2004 12:36:55 +0100, Charlie Gordon wrote:

...



What's wrong with strncat()?

He probably refers to Criminally Stupid Behaviour (TM), such as
ignoring the difference between the size of the destination
and the number of characters that still fit in, that is using
strncat(dst, src, dst_size);
instead of
strncat(dst, src, dst_size-strlen(dst)-1);
However, if you have to work with people who cannot or do not
want to read and comprehend the function documentation, this is
really just one of the many things which will go wrong.

I guess that he would rather like to pass the overall size of the
destination which is IMO no bad idea at all.
The only question to answer is then whether to make the last
character '\0' if no string terminator was encountered or not.


Cheers
Michael
 
M

Michael Mair

Michael said:
He probably refers to Criminally Stupid Behaviour (TM), such as
ignoring the difference between the size of the destination
and the number of characters that still fit in, that is using
strncat(dst, src, dst_size);
instead of
strncat(dst, src, dst_size-strlen(dst)-1);
However, if you have to work with people who cannot or do not
want to read and comprehend the function documentation, this is
really just one of the many things which will go wrong.

I guess that he would rather like to pass the overall size of the
destination which is IMO no bad idea at all.
The only question to answer is then whether to make the last
character '\0' if no string terminator was encountered or not.
Misleading: I mean in the destination (that is
strlen(dst)>= the passed size)
 
R

Richard Bos

Charlie Gordon said:
Why not write one that does what is needed.

Such as strncat()?
Or use a test and write appropriate code for each case.

strncat() is not the worst of these, but it is consistently misused in code I
come across :

So is printf().

Richard
 
C

Charlie Gordon

He probably refers to Criminally Stupid Behaviour (TM), such as
Exactly, and many variants with more subtle issues (such as what if strlen(dst)
= dst_size)

Quite true. But I make it part of house rules to avoid "booby trap programming
techniques" and part of house teachings to learn about them and detect them in
external code.
Misleading: I mean in the destination (that is
strlen(dst)>= the passed size)

Insightful remark !

The function we are talking about does not modify the destination buffer in this
case, nor in the case of dest_size <= 0.
It does not dereference dest beyond dest_size, thus does not compute
strlen(dest).
It is arguable whether it should accept NULL pointers either as source or
destination.
It returns a useful result : not the adress of the destination buffer, but an
iidication of what happened, such as the number of characters copied before the
'\0' or something negative in case of truncation, or malformed destination, or
invalid dest_size.

This is really a family of 5 functions :

int pstrlen(const char *buf, int buf_size);
int pstrcpy(char *buf, int buf_size, const char *str);
int pstrncpy(char *buf, int buf_size, const char *str, int n);
int pstrcat(char *buf, int buf_size, const char *str);
int pstrncat(char *buf, int buf_size, const char *str, int n);

I use int instead of size_t for the sizes on purpose, only ssize_t might be more
appropriate.

Chqrlie.
 
L

Lawrence Kirby

It is often misunderstood, and misused :

strncpy(dest, source, sizeof(dest)); // dangerous !
strncat(dest, source, sizeof(dest)); // worse even!

I can understand strncpy() being misunderstood, its behaviour
is oddball. strncat() is pretty simple though. You might just
as well say strcpy() is dangerous (and yes some people will
say that) but it isn't difficult to use safely.

Lawrence
 

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,769
Messages
2,569,582
Members
45,066
Latest member
VytoKetoReviews

Latest Threads

Top