469,366 Members | 2,229 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,366 developers. It's quick & easy.

Qry : Behaviour of fgets -- ?


Machine 1 :
bash-3.00$ uname -a
SunOS <hostname5.10 Generic_118822-30 sun4u sparc SUNW,Sun-Fire-280R

bash-3.00$ gcc -v
Reading specs from /usr/local/lib/gcc-lib/sparc-sun-solaris2.8/2.95.3/
specs
gcc version 2.95.3 20010315 (release)
Machine 2:
bash-2.05b$ uname -a
Linux <hostname2.4.21-4.EL #1 Fri Oct 3 18:13:58 EDT 2003 i686 i686
i386 GNU/Linux

bash-2.05b$ gcc -v
Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/3.2.3/specs
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --
infodir=/usr/share/info --enable-shared --enable-threads=posix --
disable-checking --with-system-zlib --enable-__cxa_atexit --host=i386-
redhat-linux
Thread model: posix
gcc version 3.2.3 20030502 (Red Hat Linux 3.2.3-20)

bash-2.05b$ cat fgets_fail_test.c
#include<stdio.h>
#include <string.h>
#include<stdlib.h>

/* Demo fgets failed by Raxit Sheth & Gaurav Gupta */

int main()
{
char spcontent[100],sendrepfile[100];
FILE *spfp=NULL;
memset(sendrepfile,0,100);
strcpy(sendrepfile,"/tmp/filenotexists");
if ((spfp = fopen(sendrepfile, "r")) == (FILE *)NULL)
{
printf("error in opening file %s",sendrepfile);fflush(stdout);
}
memset(spcontent, 0, sizeof(spcontent));

while (fgets(spcontent,40, spfp)!=NULL)
{
printf("The value of spcontent is
[%s]",spcontent);fflush(stdout);;
}
return 0;
}
<simillar core dump occurs on both the system>
bash-2.05b$ gcc -Wall fgets_fail_test.c -o test
bash-2.05b$ ./test
error in opening file /tmp/filenotexistsSegmentation fault (core
dumped)
bash-2.05b$ gdb ./test ./core.27887
GNU gdb Red Hat Linux (5.3.90-0.20030710.40rh)
Copyright 2003 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and
you are
welcome to change it and/or distribute copies of it under certain
conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for
details.
This GDB was configured as "i386-redhat-linux-gnu"...(no debugging
symbols found)...Using host libthread_db library "/lib/tls/
libthread_db.so.1".

Core was generated by `./test'.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /lib/tls/libc.so.6...(no debugging symbols
found)...done.
Loaded symbols for /lib/tls/libc.so.6
Reading symbols from /lib/ld-linux.so.2...(no debugging symbols
found)...done.
Loaded symbols for /lib/ld-linux.so.2
#0 0xb7506444 in fgets () from /lib/tls/libc.so.6
(gdb) where
#0 0xb7506444 in fgets () from /lib/tls/libc.so.6
#1 0x0804854b in main ()
(gdb) frame 0
#0 0xb7506444 in fgets () from /lib/tls/libc.so.6
(gdb) print errno
Cannot access memory at address 0xb74a7008
char *fgets(char *s, int n, FILE *stream)
Qry : What is the Behaviour if stream is NULL. ?

As per our understanding fgets should return NULL < and internally
gets should put check on stream, if it is not NULL then only should do
additional access of stream.

please ignore if it is known and would be great if you can point out
in the implementation detail.
--Gaurav Gupta & Raxit Sheth
http://www.barcamp.org/BarCampMumbaiOct2007 <----BarCampMumbaiOct2007

Sep 6 '07
285 7859
[fup set to c.l.c]
Rainer Weikusat wrote:
Bart van Ingen Schenau <ba**@ingen.ddns.infowrites:
>Rainer Weikusat wrote:

[...]
>>The issue is perfectly clear.

That

i = 3;
i = ++i;

means 'the value of i is now 3' is wrong,

[...]
>So, how many bug-reports have you filed with the compiler builders
that their behaviour for the code above is incorrect?

I wasn't talking about code but about the defined meaning of certain
statements. The statement above has no defined meaning.
So far, I am with you and agree.
The extreme examples of behaviour resulting from UB are also mostly
meant to wean people (mostly newbies) from the notion that all computer
programs have predictable and/or consistent behaviour. This to avoid
that they start to rely on whatever behaviour their computer shows for
UB.
Ergo: Every
claim that its defined meaning would be ... must be wrong.
And I have nobody seen making such a claim.
There is a vast difference between 'The behaviour is defined to be ...'
and 'In some instances you might see behaviour such as ..., among a
myriad of other possibilities'.

Every example that is given for behaviour that results from UB is meant
in the way of the second statement: one of a myriad of possibilities.
And the behaviour can't be wrong, because if there is no defined
behaviour, there is also no definition that forbids certain behaviours.
It doesn't
matter if the claim is something technically sensible for certain C
implementation (like the example I gave above), or some absurd piece
of non-sense intended to be entertaining (like the 'nasal daemons'):
They are both wrong.
They are wrong if they are meant to give a statement of what *will*
happen (as in a definition).
They are not wrong if they only give an example of what is possible,
without excluding any other possibilities.
>
BTW, how did you manage to miss that:

| This is completely orthogonal to the question what conceivable
| behaviour of C-implementations when processing this piece of non-C
| could be. And C is again very simple in this respect: Whatever the
| behaviour may be, it does not matter.
I did not miss it. I chose not to comment on it, but now I will.

All examples that are given for behaviour that results on encountering
UB are just what you mention in this paragraph: examples of behaviour
that a C implementation could exhibit when processing the incorrect
code.
Most people, who have questions regarding code that invokes UB, do not
have the experience needed to understand the intricacies behind UB.
They are often still in the stage where they believe that if the
compiler can generate an executable, then the code must be correct.
Then we have to get them to accept that there is a difference between
compilable code and correct code and that there are classes of errors
that the compiler can't diagnose and which cause UB.
The next question is usually 'what behaviour do I get on UB?' and then
it is not enough to just say that it is undefined. This is where the
examples involving the DS9K come in.

Bart v Ingen Schenau
--
a.c.l.l.c-c++ FAQ: http://www.comeaucomputing.com/learn/faq
c.l.c FAQ: http://www.eskimo.com/~scs/C-faq/top.html
c.l.c++ FAQ: http://www.parashift.com/c++-faq-lite/
Sep 15 '07 #251
"Charlie Gordon" <ne**@chqrlie.orgwrites:
"Ben Bacarisse" <be********@bsb.me.uka écrit dans le message de news:
87************@bsb.me.uk...
<snip>
>I was looking for another function that took a "no more than n"
parameter and which does not specify (explicitly) that it does not
write any more location than the minimum required (like fgets in the
discussion). I stupidly switched from strncat to strncpy because I
thought I could make the string cuter! How daft is that? What I
should have given is something like:

char buf[4] = "\0\0c";
strncat(buf, "a", 3);
buf[1] = 'b';
puts(buf);

We all know what should happen, but I can't see how the wording rules
out the same memset(buf, 0, 3) suggested for fgets. Similarly, the
second example should have been:

char buf[2] = "";
strncat(buf, "x", 20);

Given the operational description, only two bytes are written, but the
same goes for fgets -- the standard only states what is read and
written but it does not preclude other modifications.

Actually, the wording for strncat is unambiguous about how many characters
can be changed in the destination buffer: .

C99 7.21.3.2p2
The strncat function appends not more than n characters (a null character
and
characters that follow it are not appended) from the array pointed to by s2
to the end of
the string pointed to by s1. The initial character of s2 overwrites the null
character at the
end of s1. A terminating null character is always appended to the
result.264) If copying
takes place between objects that overlap, the behavior is undefined.

264) Thus, the maximum number of characters that can end up in the array
pointed to by s1 is
strlen(s1)+n+1.

The wording is not cristal clear, but s1 is only changed by appending
characters from s2 and the null and following characters are not appended,
and then a (single) terminating null character is always appended.
OK. I have always taken "it does this" to mean "... and nothing else"
but doubt has been raised about fgets and mbstowcs has an explicit
"only n chars written" clause. Do you feel that fgets is similarly
unambiguous?

--
Ben.
Sep 15 '07 #252
"Ben Bacarisse" <be********@bsb.me.uka écrit dans le message de news:
87************@bsb.me.uk...
<snip>
OK. I have always taken "it does this" to mean "... and nothing else"
but doubt has been raised about fgets and mbstowcs has an explicit
"only n chars written" clause. Do you feel that fgets is similarly
unambiguous?
7.19.7.2 The fgets function

Synopsis

1 #include <stdio.h>
char *fgets(char * restrict s, int n,
FILE * restrict stream);

Description

2 The fgets function reads at most one less than the number of characters
specified by n
from the stream pointed to by stream into the array pointed to by s. No
additional
characters are read after a new-line character (which is retained) or after
end-of-file. A
null character is written immediately after the last character read into the
array.

Returns

3 The fgets function returns s if successful. If end-of-file is encountered
and no
characters have been read into the array, the contents of the array remain
unchanged and a
null pointer is returned. If a read error occurs during the operation, the
array contents are
indeterminate and a null pointer is returned.

Except in the case of a read error, the contents of the array seems pretty
well described by the above wording. fgets read characters from the stream
into the array, and then writes a null character after the last character
read. Since characters are "read into the array", you would need additional
read/write operations to move them where they belong, had they no been read
in the proper place. No such operation is described as being performed by
fgets.

The real problems with the fgets definition in the standard are:

- why is the array size specified as int instead of size_t
- what is the behaviour of fgets for n == 0, and for n < 0 ?
- will fgets return NULL or s when called with n == 1 and the stream
contains no more characters but EOF has not yet been encountered ? (I don't
think it should attempt to read any byte from the stream, and thus cannot
detect EOF, so it should return s)
- to a lesser extend, why pollute the prototype with useless restrict
keywords

--
Chqrlie.
Sep 15 '07 #253
Rainer Weikusat wrote:
Chris Dollin <ch**********@hp.comwrites:
>Rainer Weikusat wrote:
>>There is no such thing as a form of undefined behaviour

Yes, there is. /Every/ program behaviour is an example of undefined
behaviour (as it is defined by the C standard).

That's a claim which should be easy to prove: Assuming you are not
deliberatetly misunderstanding me, you appear to claim that 'undefined
behavious' is actually behaviour defined by the C-standard.
chris.dollin isn't claiming that; you've misread his parentheses,
which should be bound to "undefined behaviour", not "every program
behaviour".
>The standard puts constraints on the behaviour of a program: it
says certain things are not permitted (and consequently that
others are required). In the specific case of "undefined behaviour",
there are /no constraints applied/, so all behaviours are
acceptable.

More correctly (as I have written several times now): There is no such
thing as 'acceptable behaviour' for these case (provided you cannot
magically come up with a positive definition of this beahviour)
because no acceptable behaviour is defined.
Yes, you've written this several times, and been wrong every one
of them. /Because/ no requirements are given by the standard,
/every/ behaviour is acceptable.

--
Far-Fetched Hedgehog
"I just wonder when we're going to have to sit down and re-evaluate
our decision-making paradigm." /Sahara/

Sep 16 '07 #254
Bart van Ingen Schenau wrote:
Chris Dollin wrote:
>Francis Glassborow wrote:
>>[some examples of UB that actually happened]
What part of the Standard prevents those things from happening when
a conforming program executes -- better, which stop an implementation
that does these things from being a conformant implementation?
How about clause 5.1.2.3/5, which loosely translated states that, when
observing the side-effects of a program, the user may not be able to
tell the difference between execution on the abstract machine and
execution on the actual machine.
I /think/ that can only apply to those aspects of the implementation
observable by the abstract machine.

Any other offers?

--
Far-Fetched Hedgehog
"Never ask that question!" Ambassador Kosh, /Babylon 5/

Sep 16 '07 #255
"Charlie Gordon" <ne**@chqrlie.orgwrites:
"Richard" <rg****@gmail.coma écrit dans le message de news:
eu************@desktop.thrasymachus...
>Kelsey Bjarnason <kb********@gmail.comwrites:
>>[snips]

On Fri, 14 Sep 2007 13:12:44 +0200, Richard wrote:

You need to run this past me again. Why shouldn't people who don't know
what they are doing not use it?

You mean why _should_ they not use it? Because people who don't know
what

I was making a joke and I think,yes, there is one too many
negatives.. You see, if people dont know how to use an API then they,
well, shouldn't. It is obvious. But they can learn by doing and with
judicous test cases, and debug cycles they will learn to use it
properly.

The situation is much worse than you make it sound: they don't know the
semantics, but they think they do. They write code that seems to work as
they expect but contains bugs waiting to bite... just like gets and
sprintf.
Who is "they"? Would you let them use malloc too in case they forgot to
free the memory? Which arbitrary rules are you using to decide "over
complexity"? strncpy is as basic as they get if oyu have a clue about "C
strings".

>
>>they're doing write bad and often dangerous code. Give 'em a spoon
instead. :)

or, tell them to read the API.

I agree: show them the API as an explanation for why they should not use
strncpy.
Huh? How? Why? What is so difficult? Shall we stop them using printf in
case they pass a float instead of an int and the resulting output causes
the process on the end of the pipe to crash an aircraft?
>
>>>
As to why he's suggesting not using it, if I had to guess I'd say
something along the lines of unlike pretty much every other string
function, this one has a nasty tendency to produce non-null-terminated
character arrays; if coders aren't aware of this or fail to pay attention
to it, bad things can happen.

As can i++ if you dont keep an eye on the index limit for an array.

It is bogus advice.

There is *nothing* wrong with strncpy and it is used in millions of
lines of code. In many ways you could say its safer to use since it wont
overwrite memory if the source string is bad.

to reach millions, you need to count the binaries produced.
No I don't. I said "lines of code". Not binaries.
>
You cannot decently say that there be *nothing* wrong with it: its precise
semantics make it almost useless, are conter-intuitive and are vastly
misunderstood, and misused...
Not in my, reasonably extensive, experience of rather large code bases
written in C.
>
>strtok, on the other hand .....

Why did C99 not include reentrant versions of strtok and friends
baffles me.
Probably because the pedants spent too much time arguing about when a
char was an int and when it wasn't.

Sep 16 '07 #256
["Followup-To:" header set to comp.lang.c.]
On 2007-09-16 19:30, Richard <rg****@gmail.comwrote:
"Charlie Gordon" <ne**@chqrlie.orgwrites:
>"Richard" <rg****@gmail.coma écrit dans le message de news:
eu************@desktop.thrasymachus...
>>Kelsey Bjarnason <kb********@gmail.comwrites:

[snips]

On Fri, 14 Sep 2007 13:12:44 +0200, Richard wrote:

You need to run this past me again. Why shouldn't people who don't know
what they are doing not use it?

You mean why _should_ they not use it? Because people who don't know
what

I was making a joke and I think,yes, there is one too many
negatives.. You see, if people dont know how to use an API then they,
well, shouldn't. It is obvious. But they can learn by doing and with
judicous test cases, and debug cycles they will learn to use it
properly.

The situation is much worse than you make it sound: they don't know the
semantics, but they think they do. They write code that seems to work as
they expect but contains bugs waiting to bite... just like gets and
sprintf.

Who is "they"? Would you let them use malloc too in case they forgot to
free the memory? Which arbitrary rules are you using to decide "over
complexity"? strncpy is as basic as they get if oyu have a clue about "C
strings".
The problem with strncpy is that is does NOT produce "C strings".

The result of

char *s = "a string of at least 80 characters ...";
char buf[80];
strncpy(buf, s, 80);

is buf not being zero-terminated, which makes it unsafe to use with
almost all other string functions. And no, strncpy(buf, s, 79) doesn't
help either, unless you add an additional buf[79] = '\0'.

strncpy is intended for filling zero-padded (not zero-terminated)
buffers of fixed width. That may be useful for certain file formats
(wtmp/utmp have been mentioned, the original UNIX directory structure
also comes to mind), but it is almost always the wrong tool when you
deal with "C strings".

>>>they're doing write bad and often dangerous code. Give 'em a spoon
instead. :)

or, tell them to read the API.

I agree: show them the API as an explanation for why they should not use
strncpy.

Huh? How? Why? What is so difficult?
It's not difficult it's just the wrong tool for the job.

hp
--
_ | Peter J. Holzer | I know I'd be respectful of a pirate
|_|_) | Sysadmin WSR | with an emu on his shoulder.
| | | hj*@hjp.at |
__/ | http://www.hjp.at/ | -- Sam in "Freefall"
Sep 16 '07 #257
"Douglas A. Gwyn" <DA****@null.netwrote:
Keith Thompson wrote:
Ok, but I find this particular instance of that (having a keyword in a
delaration that really has no more meaning than a comment, even though
there *could* be an obvious meaning for it) to be a bit too subtle.
If something is meaningless, it doesn't belong in the language. ...

Well, it isn't meaningless, but it doesn't affect code generation.

There is a proposal before the C standards committee to adopt
somethings like Microsoft's __declspec facility for annotating
C source code with "attributes" that are outside the scope of
the current C standard. I suspect every experienced C
programmer has occasionally thought that there ought to be
somethings of the sort. Recall /*NOTREACHED*/ to avoid a
spurious warning from "lint"? There is a __declspec attribute
that has the same meaning.
Don't we already have #pragma for this?

Richard
Sep 17 '07 #258
"Richard" <rg****@gmail.coma écrit dans le message de news:
pr************@individual.net...
"Charlie Gordon" <ne**@chqrlie.orgwrites:
>"Richard" <rg****@gmail.coma écrit dans le message de news:
eu************@desktop.thrasymachus...
>>Kelsey Bjarnason <kb********@gmail.comwrites:

[snips]

On Fri, 14 Sep 2007 13:12:44 +0200, Richard wrote:

You need to run this past me again. Why shouldn't people who don't
know
what they are doing not use it?

You mean why _should_ they not use it? Because people who don't know
what

I was making a joke and I think,yes, there is one too many
negatives.. You see, if people dont know how to use an API then they,
well, shouldn't. It is obvious. But they can learn by doing and with
judicous test cases, and debug cycles they will learn to use it
properly.

The situation is much worse than you make it sound: they don't know the
semantics, but they think they do. They write code that seems to work as
they expect but contains bugs waiting to bite... just like gets and
sprintf.

Who is "they"? Would you let them use malloc too in case they forgot to
free the memory? Which arbitrary rules are you using to decide "over
complexity"? strncpy is as basic as they get if oyu have a clue about "C
strings".
They is a large proportion of C programmers.
Forgetting to call free causes problems in very few programs. I'm not
advocating sloppiness about it, and it is much easier to understand and
master malloc/free than strncpy. realloc is a different matter of course, I
definitely recommend for newbies to stay away from it.
the problem with strncpy is *precisely* that it does not deal with C
strings. It's purpose is to initialize fixed size, 0 padded, non
necessarily 0 terminated char arrays. Such objects are not use anywhere
else in the Standard, and very rarely in real applications.
>>>they're doing write bad and often dangerous code. Give 'em a spoon
instead. :)

or, tell them to read the API.

I agree: show them the API as an explanation for why they should not use
strncpy.

Huh? How? Why? What is so difficult? Shall we stop them using printf in
case they pass a float instead of an int and the resulting output causes
the process on the end of the pipe to crash an aircraft?
Good compilers will detect such errors at compile time. Of course in your
example, the float is passed as a double, but you knew that... A more subtle
and proplematic example is this:

printf("%.*s\n", sizeof(buf), buf);

This printf format is needed to output the contents of a non 0 terminated
buffer (such as the one strnpy could have initialized). The problem here is
printf expects an int as the value for the '*' place-holder, and sizeof(buf)
is a size_t, a type that can be larger than an int these days (long on linux
64bit, long long on Windows 64 bits where int is 32 bits on both).

Yes, printf has its intricacies, but newbies rarely run into them.
Conversely, wrongly named strncpy is misused almost all the time, especially
by newbies.
>>>As to why he's suggesting not using it, if I had to guess I'd say
something along the lines of unlike pretty much every other string
function, this one has a nasty tendency to produce non-null-terminated
character arrays; if coders aren't aware of this or fail to pay
attention
to it, bad things can happen.

As can i++ if you dont keep an eye on the index limit for an array.

It is bogus advice.

There is *nothing* wrong with strncpy and it is used in millions of
lines of code. In many ways you could say its safer to use since it wont
overwrite memory if the source string is bad.

to reach millions, you need to count the binaries produced.

No I don't. I said "lines of code". Not binaries.
Millions of lines with strncpy in them ?
You may be right, www.google.com/codesearch come up with 314000 matches for
strncpy !
So many bugs waiting to bite !
>You cannot decently say that there be *nothing* wrong with it: its
precise
semantics make it almost useless, are conter-intuitive and are vastly
misunderstood, and misused...

Not in my, reasonably extensive, experience of rather large code bases
written in C.
Well I don't know what code bases you are refering to, and I could not find
any open source code with your copyright (Richard G. Riley). But take a
second look...

Use google codesearch, look to strncpy sizeof... check the first 4: all
wrong one way or another.
Even openssl gets it wrong:

char e_buf[32+1]; /* replace 32 by 8 ? */

/* Copy at most 32 chars of password */
strncpy (e_buf, buf, sizeof(e_buf));

/* Make sure we have a delimiter */
e_buf[sizeof(e_buf)-1] = '\0';

Granted there is no bug here, at least the comment is wrong, and the
occasional reader of this code will be mislead.
>>strtok, on the other hand .....

Why did C99 not include reentrant versions of strtok and friends
baffles me.

Probably because the pedants spent too much time arguing about when a
char was an int and when it wasn't.
Or figuring iso646.h.

--
Chqrlie
Sep 17 '07 #259
Richard Bos wrote:
"Douglas A. Gwyn" <DA****@null.netwrote:
There is a proposal before the C standards committee to adopt
somethings like Microsoft's __declspec facility for annotating
C source code with "attributes" that are outside the scope of
the current C standard. ...
Don't we already have #pragma for this?
Also the _Pragma operator, which might be closer to what is desired.
I'm sure that will come up in the technical discussion next month.

Anyway, the request is to standardize this facility in some form.
Sep 17 '07 #260
[snips]

On Sun, 16 Sep 2007 23:19:51 +0200, Peter J. Holzer wrote:
The problem with strncpy is that is does NOT produce "C strings".
It does when told to.
The result of

char *s = "a string of at least 80 characters ...";
char buf[80];
strncpy(buf, s, 80);

is buf not being zero-terminated, which makes it unsafe to use with
almost all other string functions. And no, strncpy(buf, s, 79) doesn't
help either, unless you add an additional buf[79] = '\0'.
Keerect. Which is to say, it is - like any other function - only really
reliable when used properly.
also comes to mind), but it is almost always the wrong tool when you
deal with "C strings".
Actually, I kinda like the idea. "I need up to N chars of this buffer, so
even if it's 3N chars long, only gimme what I need." Makes sense; if
nothing else it lessens the likelihood of a buffer overflow, as you can
specify exactly how much data to copy. Not that there aren't other
methods, but as a library function this one will, presumably, be "more
optimal" than a loop and have sufficiently different semantics from memcpy
as to make it useful on its own - you just need to remember to terminate
the resultant buffer.
Sep 17 '07 #261
"Douglas A. Gwyn" <DA****@null.netwrites:
Richard Bos wrote:
>"Douglas A. Gwyn" <DA****@null.netwrote:
There is a proposal before the C standards committee to adopt
somethings like Microsoft's __declspec facility for annotating
C source code with "attributes" that are outside the scope of
the current C standard. ...
Don't we already have #pragma for this?

Also the _Pragma operator, which might be closer to what is desired.
I'm sure that will come up in the technical discussion next month.

Anyway, the request is to standardize this facility in some form.
Currently a use of the _Pragma operator is described as a "unary
operator expression". I assume that means it can apear only in a
context where a unary-expression could appear. (It's odd, though,
that 6.10.9 calls this a "unary operator expression", while 6.5.3 uses
the term "unary-expression".)

But allowing _Pragma in more contexts shouldn't be a problem.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Sep 17 '07 #262
On 2007-09-17 16:10, Kelsey Bjarnason <kb********@gmail.comwrote:
[snips]

On Sun, 16 Sep 2007 23:19:51 +0200, Peter J. Holzer wrote:
>The problem with strncpy is that is does NOT produce "C strings".

It does when told to.
No. There is no way you can tell strncpy to produce a zero-terminated
string. You have to add the terminator yourself.

>The result of

char *s = "a string of at least 80 characters ...";
char buf[80];
strncpy(buf, s, 80);

is buf not being zero-terminated, which makes it unsafe to use with
almost all other string functions. And no, strncpy(buf, s, 79) doesn't
help either, unless you add an additional buf[79] = '\0'.

Keerect. Which is to say, it is - like any other function - only really
reliable when used properly.
Oh, strncpy is very reliable. It just does reliably the wrong thing.
>also comes to mind), but it is almost always the wrong tool when you
deal with "C strings".

Actually, I kinda like the idea. "I need up to N chars of this buffer, so
even if it's 3N chars long, only gimme what I need."
But strncpy doesn't give you "up to N chars". It always gives you
exactly N chars. That's wasteful if your source string is shorter and
unsafe if it is longer. strncat or snprintf is almost always the better
choice. Even strcpy is better - at least then you know you have to be
careful.

Makes sense;
If you are constructing records for some specific file formats, yes. In
no other case.
if nothing else it lessens the likelihood of a buffer overflow, as you
can specify exactly how much data to copy. Not that there aren't
other methods, but as a library function this one will,
strncat and snprintf are standard library functions, too.
(But both have their warts, too. There must be some law that if there
are several competing libraries, it is always the one with the least
useful and most bizarre behaviour which gets standardized).

hp
--
_ | Peter J. Holzer | I know I'd be respectful of a pirate
|_|_) | Sysadmin WSR | with an emu on his shoulder.
| | | hj*@hjp.at |
__/ | http://www.hjp.at/ | -- Sam in "Freefall"
Sep 17 '07 #263
"Peter J. Holzer" <hj*********@hjp.atwrites:
On 2007-09-17 16:10, Kelsey Bjarnason <kb********@gmail.comwrote:
>[snips]

On Sun, 16 Sep 2007 23:19:51 +0200, Peter J. Holzer wrote:
>>The problem with strncpy is that is does NOT produce "C strings".

It does when told to.

No. There is no way you can tell strncpy to produce a zero-terminated
string. You have to add the terminator yourself.
Misleading.

Sep 17 '07 #264
On Mon, 17 Sep 2007 21:57:27 +0200, Peter J. Holzer wrote:
On 2007-09-17 16:10, Kelsey Bjarnason <kb********@gmail.comwrote:
>[snips]

On Sun, 16 Sep 2007 23:19:51 +0200, Peter J. Holzer wrote:
>>The problem with strncpy is that is does NOT produce "C strings".

It does when told to.

No. There is no way you can tell strncpy to produce a zero-terminated
string. You have to add the terminator yourself.
char dst[128];
char *src = "abc";
strncpy( dst, src, sizeof(dst) );

This *won't* produce a proper null terminated string in dst? I have to
add the terminator myself? News to me.
>Keerect. Which is to say, it is - like any other function - only really
reliable when used properly.

Oh, strncpy is very reliable. It just does reliably the wrong thing.
Copies n chars, padding as necessary - exactly as it's described to.
Yeah, fine, if it acted a little more like, say, fgets such that the size
parameter was actually size-1 and space was left over for a terminating
null, great, agreed, this wouldn't be a bad design either. Perhaps even a
better design.

On the other hand, if I'm trying to, oh, use it to insert into an existing
string, I probably don't want terminators stuffed in, so the way it works
now is viable, too.
>Actually, I kinda like the idea. "I need up to N chars of this buffer, so
even if it's 3N chars long, only gimme what I need."
But strncpy doesn't give you "up to N chars". It always gives you
exactly N chars.
Not what I said; I said "up to N chars of this buffer". It *cannot*
(assuming the source buffer is a proper string) give me N chars of it if
the buffer contains fewer than N chars.
That's wasteful if your source string is shorter and
unsafe if it is longer. strncat or snprintf is almost always the better
choice. Even strcpy is better - at least then you know you have to be
careful.
Yeah, strncpy ain't perfect by any means. C++ strings are somewhat saner
overall, but then, this ain't C++.
>if nothing else it lessens the likelihood of a buffer overflow, as you
can specify exactly how much data to copy. Not that there aren't other
methods, but as a library function this one will,

strncat and snprintf are standard library functions, too.
And this has what, precisely, to do with the "more optimal" comment made?
Sep 17 '07 #265
"Douglas A. Gwyn" <DA****@null.netwrote:
Richard Bos wrote:
"Douglas A. Gwyn" <DA****@null.netwrote:
There is a proposal before the C standards committee to adopt
somethings like Microsoft's __declspec facility for annotating
C source code with "attributes" that are outside the scope of
the current C standard. ...
Don't we already have #pragma for this?

Also the _Pragma operator, which might be closer to what is desired.
I'm sure that will come up in the technical discussion next month.

Anyway, the request is to standardize this facility in some form.
Not being a Committee member, I'm not allowed to vote - but I vote
against. It's completely unnecessary.

Richard
Sep 18 '07 #266
Richard Bos wrote:
"Douglas A. Gwyn" <DA****@null.netwrote:
There is a proposal before the C standards committee to adopt
somethings like Microsoft's __declspec facility for annotating
C source code with "attributes" that are outside the scope of
the current C standard. ...
Anyway, the request is to standardize this facility in some form.
Not being a Committee member, I'm not allowed to vote - but I vote
against. It's completely unnecessary.
An argument for standardization is that there is a lot of
(possibly) otherwise portable C source code around that
cannot be readily ported to other platforms due to
containing such decorations. The fact that more than one
major compiler implementation added such a feature seems
to indicate that there is a practical need for it.

That said, I'm not happy with the idea.
Sep 18 '07 #267
On 2007-09-17 23:35, Kelsey Bjarnason <kb********@gmail.comwrote:
On Mon, 17 Sep 2007 21:57:27 +0200, Peter J. Holzer wrote:
>On 2007-09-17 16:10, Kelsey Bjarnason <kb********@gmail.comwrote:
>>[snips]
On Sun, 16 Sep 2007 23:19:51 +0200, Peter J. Holzer wrote:

The problem with strncpy is that is does NOT produce "C strings".

It does when told to.

No. There is no way you can tell strncpy to produce a zero-terminated
string. You have to add the terminator yourself.

char dst[128];
char *src = "abc";
strncpy( dst, src, sizeof(dst) );

This *won't* produce a proper null terminated string in dst?
You don't *tell* strncpy to produce a zero-terminated string here. It
just happens to do so because the source string is shorter than the
destination buffer. If src happens to point to a longer string, dst
won't be zero-terminated.

And this is exactly the kind of buggy code I was thinking about: The
code is "safe" in exactly the same situation when strcpy would have been
"safe", too. When strcpy isn't safe, this isn't either. The failure is
just a bit more subtle, and less likely to be noticed in a code audit.

To be safe you either need to check the length of src (but then you can
use strcpy, too) or manually add the terminator.

And of course you are needlessly filling a lot of memory with zeros.
In your example, instead of writing 4 bytes, you write 128 bytes: An
overhead of 3100%!

On the other hand, if I'm trying to, oh, use it to insert into an existing
string, I probably don't want terminators stuffed in, so the way it works
now is viable, too.
You just have to determine the length beforehand. If you already know
the length, why don't you use memcpy (or memmove)? Your defense of
strncpy gets more and more far-fetched.

>>if nothing else it lessens the likelihood of a buffer overflow, as you
can specify exactly how much data to copy. Not that there aren't other
methods, but as a library function this one will,

strncat and snprintf are standard library functions, too.

And this has what, precisely, to do with the "more optimal" comment made?
You were essentially saying "strncpy is more optimal than strncat
because strncpy is a library function". Please consider this sentence
and think again whether it makes any sense.

hp
--
_ | Peter J. Holzer | I know I'd be respectful of a pirate
|_|_) | Sysadmin WSR | with an emu on his shoulder.
| | | hj*@hjp.at |
__/ | http://www.hjp.at/ | -- Sam in "Freefall"
Sep 18 '07 #268
Kelsey Bjarnason said:

<snip>
I said no such thing. Learn to read.
You are Dan Pop, and I claim my five pounds.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Sep 18 '07 #269
On 2007-09-18 21:47, Kelsey Bjarnason <kb********@gmail.comwrote:
[snips]

On Tue, 18 Sep 2007 20:05:10 +0200, Peter J. Holzer wrote:
>>char dst[128];
char *src = "abc";
strncpy( dst, src, sizeof(dst) );

This *won't* produce a proper null terminated string in dst?

You don't *tell* strncpy to produce a zero-terminated string here.

Sure I do - by specifying a destination buffer larger than the source.
If you can be sure of that there is no advantage in using strncpy over
strcpy.

>>And this has what, precisely, to do with the "more optimal" comment
made?
>You were essentially saying "strncpy is more optimal than strncat
because strncpy is a library function".

I said no such thing. Learn to read. Here, I'll quote it for you:

"...but as a library function this one will, presumably, be "more
optimal" than a loop..."
Which is a strawman, because a loop is not the only alternative to
strncpy.

hp
--
_ | Peter J. Holzer | I know I'd be respectful of a pirate
|_|_) | Sysadmin WSR | with an emu on his shoulder.
| | | hj*@hjp.at |
__/ | http://www.hjp.at/ | -- Sam in "Freefall"
Sep 19 '07 #270
Peter J. Holzer said:
On 2007-09-18 21:47, Kelsey Bjarnason <kb********@gmail.comwrote:
>[snips]

On Tue, 18 Sep 2007 20:05:10 +0200, Peter J. Holzer wrote:
>>>char dst[128];
char *src = "abc";
strncpy( dst, src, sizeof(dst) );

This *won't* produce a proper null terminated string in dst?

You don't *tell* strncpy to produce a zero-terminated string here.

Sure I do - by specifying a destination buffer larger than the source.

If you can be sure of that there is no advantage in using strncpy over
strcpy.
True enough, but then strncpy was not designed to be used in place of
strcpy. The strncpy function is designed for copying substrings, and it
does that job reasonably well (although, it can be argued, not as well as
memcpy does it). It is not supposed to be a safe alternative to strcpy,
which is just as well because it would do the job very badly indeed.

<snip>

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Sep 19 '07 #271
Richard Heathfield <rj*@see.sig.invalidwrites:
[...]
True enough, but then strncpy was not designed to be used in place of
strcpy. The strncpy function is designed for copying substrings, and it
does that job reasonably well (although, it can be argued, not as well as
memcpy does it). It is not supposed to be a safe alternative to strcpy,
which is just as well because it would do the job very badly indeed.
And the real problem is that the name "strncpy" implies that that's
exactly what it's supposed to be. strncat(), for example, behaves
like strcat(), except that it lets you set a limit on the length of
the target string, while still guaranteeing that it will be properly
zero-terminated; similarly for snprintf().

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Sep 19 '07 #272
Keith Thompson said:
Richard Heathfield <rj*@see.sig.invalidwrites:
[...]
>[strncpy] is not supposed to be a safe alternative to
strcpy, which is just as well because it would do the job very badly
indeed.

And the real problem is that the name "strncpy" implies that that's
exactly what it's supposed to be.
I don't dispute that it's a lousy name.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Sep 19 '07 #273
"Richard Heathfield" <rj*@see.sig.invalida écrit dans le message de news:
Ke******************************@bt.com...
Keith Thompson said:
>Richard Heathfield <rj*@see.sig.invalidwrites:
[...]
>>[strncpy] is not supposed to be a safe alternative to
strcpy, which is just as well because it would do the job very badly
indeed.

And the real problem is that the name "strncpy" implies that that's
exactly what it's supposed to be.

I don't dispute that it's a lousy name.
More precisely, it is a lousy spec for such a name.
It would have been quite natural if strncpy was specified as doing this:

/* too bad this is not real */
int strncpy(char *s, size_t size, const char *p) {
return snprintf(s, size, "%s", p);
}

But we cannot rewrite history.
Given the current and unfixable spec for strncpy, the reasonable thing to do
is deprecate its use.

--
Chqrlie.
Sep 19 '07 #274
"Keith Thompson" <ks***@mib.orga écrit dans le message de news:
ln************@nuthaus.mib.org...
Richard Heathfield <rj*@see.sig.invalidwrites:
[...]
>True enough, but then strncpy was not designed to be used in place of
strcpy. The strncpy function is designed for copying substrings, and it
does that job reasonably well (although, it can be argued, not as well as
memcpy does it). It is not supposed to be a safe alternative to strcpy,
which is just as well because it would do the job very badly indeed.

And the real problem is that the name "strncpy" implies that that's
exactly what it's supposed to be. strncat(), for example, behaves
like strcat(), except that it lets you set a limit on the length of
the target string, while still guaranteeing that it will be properly
zero-terminated; similarly for snprintf().
Your statement holds for snprintf, but not for strncat: the num argument is
not "a limit on the target string", it is a limit on the number of
characters to copy from the source string. As such, it is no safer than
strcat itself. It does guarantee zero-termination, but can still overflow
the destination string!

--
Chqrlie.
Sep 19 '07 #275
"Charlie Gordon" <ne**@chqrlie.orgwrites:
"Keith Thompson" <ks***@mib.orga écrit dans le message de news:
ln************@nuthaus.mib.org...
>Richard Heathfield <rj*@see.sig.invalidwrites:
[...]
>>True enough, but then strncpy was not designed to be used in place of
strcpy. The strncpy function is designed for copying substrings, and it
does that job reasonably well (although, it can be argued, not as well as
memcpy does it). It is not supposed to be a safe alternative to strcpy,
which is just as well because it would do the job very badly indeed.

And the real problem is that the name "strncpy" implies that that's
exactly what it's supposed to be. strncat(), for example, behaves
like strcat(), except that it lets you set a limit on the length of
the target string, while still guaranteeing that it will be properly
zero-terminated; similarly for snprintf().

Your statement holds for snprintf, but not for strncat: the num argument is
not "a limit on the target string", it is a limit on the number of
characters to copy from the source string. As such, it is no safer than
strcat itself. It does guarantee zero-termination, but can still overflow
the destination string!
Ok, good point. But one could argue, I suppose, that strncat's target
string begins just after the existing string. If you know the size of
the target array and the current length of the string it contains, you
can use strncat safely.

In fact, I think a simple way to implement what strncpy() *should*
have been is to call strncat() after setting the first character of
the target array to '\0' (though since the count doesn't include the
terminating '\0' you need to watch out for off-by-one errors).

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Sep 19 '07 #276
On Tue, 18 Sep 2007 22:36:10 +0000, Richard Heathfield wrote:
Kelsey Bjarnason said:

<snip>
>I said no such thing. Learn to read.

You are Dan Pop, and I claim my five pounds.
Would that I were. There was a dude with a head on his shoulders. Not
that there aren't a few such others about, yourself obviously included.

That said, okay, fine, I got a bit grumpy; call it an artifact of the
sudden infusion of apparent idiocy into the group. I'll spnak myself and
try to be nice, even if I do feel more like chewing their faces off than
anything.
Sep 20 '07 #277
On 2007-09-19 07:03, Richard Heathfield <rj*@see.sig.invalidwrote:
Peter J. Holzer said:
>On 2007-09-18 21:47, Kelsey Bjarnason <kb********@gmail.comwrote:
>>[snips]
On Tue, 18 Sep 2007 20:05:10 +0200, Peter J. Holzer wrote:
char dst[128];
char *src = "abc";
strncpy( dst, src, sizeof(dst) );
>
This *won't* produce a proper null terminated string in dst?

You don't *tell* strncpy to produce a zero-terminated string here.

Sure I do - by specifying a destination buffer larger than the source.

If you can be sure of that there is no advantage in using strncpy over
strcpy.

True enough, but then strncpy was not designed to be used in place of
strcpy.
[...]
It is not supposed to be a safe alternative to strcpy,
Exactly. That's what I was trying to explain. However, it seems I didn't
get that point across to Kelsey, and while trying to find yet another
way to explain the same thing I got a bit unfocused.

hp
--
_ | Peter J. Holzer | I know I'd be respectful of a pirate
|_|_) | Sysadmin WSR | with an emu on his shoulder.
| | | hj*@hjp.at |
__/ | http://www.hjp.at/ | -- Sam in "Freefall"
Sep 20 '07 #278
"Douglas A. Gwyn" <DA****@null.netwrote:
Richard Bos wrote:
"Douglas A. Gwyn" <DA****@null.netwrote:
There is a proposal before the C standards committee to adopt
somethings like Microsoft's __declspec facility for annotating
C source code with "attributes" that are outside the scope of
the current C standard. ...
Anyway, the request is to standardize this facility in some form.
Not being a Committee member, I'm not allowed to vote - but I vote
against. It's completely unnecessary.

An argument for standardization is that there is a lot of
(possibly) otherwise portable C source code around that
cannot be readily ported to other platforms due to
containing such decorations. The fact that more than one
major compiler implementation added such a feature seems
to indicate that there is a practical need for it.
Possibly, but it has the same problems as #pragma: if you do not
standardise the options it controls the result is still unportable,
because one implementation's options can easily clash with another's;
but if you _do_ standardise those options, you miss the very point of
the attributes being outside the Standard's scope. In that light, you
might as well leave them as #pragma's.
That said, I'm not happy with the idea.
Neither am I.
Sep 21 '07 #279
Richard Bos wrote:
but if you _do_ standardise those options, you miss the very point of
the attributes being outside the Standard's scope.
The idea is to standardize both the syntax and semantics of some
selected set of attributes.
Sep 21 '07 #280
jacob navia wrote:
__declspec(naked)
A function declared with this attribute will have neither
a prologue nor an epilogue, not even a "return" assembly
instruction. This allows
o To write interrupt handlers and similar in assembly
o To define aliases for functions that are already
defined.
The requirements for interfacing an interrupt handler to a
C function vary across platforms; simply omitting the usual
function prologue and postlogue does not work in many cases.
(Registers need to be saved and restored, etc.) It would be
nice to have support specifically for interrupt handlers.

I'm not sure why we need aliases for functions, at least
more than can be accomplished using #define.
Sep 25 '07 #281
Douglas A. Gwyn wrote:
jacob navia wrote:
>__declspec(naked)
A function declared with this attribute will have neither
a prologue nor an epilogue, not even a "return" assembly
instruction. This allows
o To write interrupt handlers and similar in assembly
o To define aliases for functions that are already
defined.

The requirements for interfacing an interrupt handler to a
C function vary across platforms; simply omitting the usual
function prologue and postlogue does not work in many cases.
(Registers need to be saved and restored, etc.) It would be
nice to have support specifically for interrupt handlers.

I'm not sure why we need aliases for functions, at least
more than can be accomplished using #define.
After reflecting about this, I agree it is not a good idea to
include this stuff, as I said already in this same thread.

Aliases are needed to export the same function from a shared
object with different names, for instance. But this is also
highly system specific, so I would not propose including it
in the standard.

jacob
Sep 25 '07 #282
Douglas A. Gwyn wrote, On 25/09/07 15:24:
jacob navia wrote:
>__declspec(naked)
A function declared with this attribute will have neither
a prologue nor an epilogue, not even a "return" assembly
instruction. This allows
o To write interrupt handlers and similar in assembly
o To define aliases for functions that are already
defined.

The requirements for interfacing an interrupt handler to a
C function vary across platforms; simply omitting the usual
function prologue and postlogue does not work in many cases.
(Registers need to be saved and restored, etc.) It would be
nice to have support specifically for interrupt handlers.
Agreed. I would vote for __interrupt or __interrupt(N) if support for
interrupts where to be added, then leave it up to the compiler to do the
right thing whatever that is.
I'm not sure why we need aliases for functions, at least
more than can be accomplished using #define.
I can't see any good use for function aliases either.
--
Flash Gordon
Sep 25 '07 #283
Flash Gordon wrote:
Richard Bos wrote, On 28/09/07 10:36:
Threading falls outside the scope of the Standard.
Does that always have to be completely the case?
Actually, the C++ and C standards committees are working on
specifications for threading models. The motivation is that
many current applications rely on having multiple threads of
execution, perhaps because genuine IPC is too expensive on
most current platforms. Threads raise a number of issues
about how execution can be interleaved; this wouldn't be of
much concern if programmers always used protective measures
such as locks to serialize access to shared objects, but for
some reason many of them want to omit such mechanisms. It
doesn't help that popular current multiple-core processors
don't have good support for synchronizing memory caches.
Oct 1 '07 #284
Douglas A. Gwyn wrote, On 01/10/07 21:24:
Flash Gordon wrote:
>Richard Bos wrote, On 28/09/07 10:36:
>>Threading falls outside the scope of the Standard.
Does that always have to be completely the case?

Actually, the C++ and C standards committees are working on
specifications for threading models.
That certainly is interesting, and could motivate people to push for the
new standard to actually be implemented.

<snip>
most current platforms. Threads raise a number of issues
about how execution can be interleaved; this wouldn't be of
much concern if programmers always used protective measures
such as locks to serialize access to shared objects, but for
some reason many of them want to omit such mechanisms.
I can't speak for others, but I can see the use for something equivalent
to "volatile sig_Atomic_t" so you can write a single small value and
know that the other thread will either see the old or new value and not
some mix of the two. However, for larger values or where there is a
read/modify/write cycle I would expect to have to use some form of locking.
It
doesn't help that popular current multiple-core processors
don't have good support for synchronizing memory caches.
Ouch.

I assume you are also trying to define something that can easily be
implemented on Windows and POSIX without having to change the way the OS
works or have a large "compatibility" layer. Must be quite some challenge.

I could certainly find use for even a simple standardised threading
implementation, so I wish you luck with it.
--
Flash Gordon
Oct 2 '07 #285
Flash Gordon <sp**@flash-gordon.me.ukwrote:
Richard Bos wrote, On 28/09/07 10:36:
All the alignment brouhaha is not only inherently unportable, but also
something which 99% of programmers should trust their optimisers on. You
do not want to create another register keyword.

I can see that is a risk.
Threading falls outside the scope of the Standard.

Does that always have to be completely the case?
No, but it would not be a good idea to introduce a new syntax element
for them when threading itself is not yet a part of C. If a new Standard
were to introduce a thorough, well thought out model for threading in C,
and have some of these attributes as part of that, I would have fewer or
possibly no problems with that. But the current proposal is coat first,
body afterwards.
Deprecated is exclusively of interest to implementors themselves, and
should never occur outside implementation headers; that can therefore be
handled in an implementation-specific manner in all cases - since those
headers cannot typically be used with other implementations in any case,
it is no loss if those solutions are not portable.

Deprecated is also useful for the writers of third-party libraries. If,
for example, I wrote a wonderful XML processing library that everybody
used, after a few years I might add some new interfaces to it and
deprecate others. At that point it would be useful to be able to flag
the deprecated functions as being deprecated. Note that XML processing
can be done *entirely* in standard C, so the library could be completely
portable and nothing to do with any specific implementation.
Possibly; although in that case you would want a rather more complete
syntax than the proposed one. For example, you'd want to be able to
indicate to the user-programmer both the reason for the deprecation, and
the new, better option.

Richard
Oct 10 '07 #286

This discussion thread is closed

Replies have been disabled for this discussion.

By using this site, you agree to our Privacy Policy and Terms of Use.