Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #12167 > unrolled thread
| Started by | gaoqiang <gaoqiangscut@gmail.com> |
|---|---|
| First post | 2011-10-28 01:49 -0700 |
| Last post | 2011-10-30 07:13 -0400 |
| Articles | 20 on this page of 107 — 32 participants |
Back to article view | Back to comp.lang.c
about NULL as a parameter to a libc function gaoqiang <gaoqiangscut@gmail.com> - 2011-10-28 01:49 -0700
Re: about NULL as a parameter to a libc function Mark Bluemel <mark_bluemel@pobox.com> - 2011-10-28 10:14 +0100
Re: about NULL as a parameter to a libc function gaoqiang <gaoqiangscut@gmail.com> - 2011-10-28 03:22 -0700
Re: about NULL as a parameter to a libc function Mark Bluemel <mark_bluemel@pobox.com> - 2011-10-28 11:29 +0100
Re: about NULL as a parameter to a libc function Jorgen Grahn <grahn+nntp@snipabacken.se> - 2011-10-29 07:08 +0000
Re: about NULL as a parameter to a libc function James Kuyper <jameskuyper@verizon.net> - 2011-10-28 07:05 -0400
Re: about NULL as a parameter to a libc function Keith Thompson <kst-u@mib.org> - 2011-10-28 14:15 -0700
Re: about NULL as a parameter to a libc function gordonb.4o15x@burditt.org (Gordon Burditt) - 2011-10-28 16:36 -0500
Re: about NULL as a parameter to a libc function Robert Wessel <robertwessel2@yahoo.com> - 2011-10-28 17:30 -0500
Re: about NULL as a parameter to a libc function jgharston <jgh@arcade.demon.co.uk> - 2011-10-31 10:40 -0700
Re: about NULL as a parameter to a libc function Kaz Kylheku <kaz@kylheku.com> - 2011-10-28 22:32 +0000
Re: about NULL as a parameter to a libc function Nick Keighley <nick_keighley_nospam@hotmail.com> - 2011-10-29 06:20 -0700
Re: about NULL as a parameter to a libc function "BartC" <bc@freeuk.com> - 2011-10-29 15:40 +0100
Re: about NULL as a parameter to a libc function Nick Keighley <nick_keighley_nospam@hotmail.com> - 2011-10-30 08:05 -0700
Re: about NULL as a parameter to a libc function Keith Thompson <kst-u@mib.org> - 2011-10-28 14:13 -0700
Re: about NULL as a parameter to a libc function Phil Carmody <thefatphil_demunged@yahoo.co.uk> - 2011-10-29 15:11 +0300
Re: about NULL as a parameter to a libc function Nick Keighley <nick_keighley_nospam@hotmail.com> - 2011-10-29 06:41 -0700
Re: about NULL as a parameter to a libc function Keith Thompson <kst-u@mib.org> - 2011-10-29 11:29 -0700
Re: about NULL as a parameter to a libc function Malcolm McLean <malcolm.mclean5@btinternet.com> - 2011-10-28 02:36 -0700
Re: about NULL as a parameter to a libc function Mike Manilone <mike@laptop.mike> - 2011-10-28 12:58 +0000
Re: about NULL as a parameter to a libc function James Kuyper <jameskuyper@verizon.net> - 2011-10-28 11:00 -0400
Re: about NULL as a parameter to a libc function Kenneth Brody <kenbrody@spamcop.net> - 2011-11-03 11:13 -0400
Re: about NULL as a parameter to a libc function Nick Keighley <nick_keighley_nospam@hotmail.com> - 2011-10-29 06:37 -0700
Re: about NULL as a parameter to a libc function Kenneth Brody <kenbrody@spamcop.net> - 2011-11-03 11:00 -0400
Re: about NULL as a parameter to a libc function James Kuyper <jameskuyper@verizon.net> - 2011-11-03 12:54 -0400
Re: about NULL as a parameter to a libc function Kaz Kylheku <kaz@kylheku.com> - 2011-11-03 17:08 +0000
Re: about NULL as a parameter to a libc function James Kuyper <jameskuyper@verizon.net> - 2011-11-03 13:18 -0400
Re: about NULL as a parameter to a libc function Kaz Kylheku <kaz@kylheku.com> - 2011-11-03 17:28 +0000
Re: about NULL as a parameter to a libc function James Kuyper <jameskuyper@verizon.net> - 2011-11-03 13:48 -0400
Re: about NULL as a parameter to a libc function Kaz Kylheku <kaz@kylheku.com> - 2011-11-03 17:55 +0000
Re: about NULL as a parameter to a libc function James Kuyper <jameskuyper@verizon.net> - 2011-11-03 14:12 -0400
Re: about NULL as a parameter to a libc function blp@cs.stanford.edu (Ben Pfaff) - 2011-11-03 11:22 -0700
Re: about NULL as a parameter to a libc function James Kuyper <jameskuyper@verizon.net> - 2011-11-03 14:28 -0400
Re: about NULL as a parameter to a libc function Kaz Kylheku <kaz@kylheku.com> - 2011-11-03 19:47 +0000
Re: about NULL as a parameter to a libc function James Kuyper <jameskuyper@verizon.net> - 2011-11-03 16:19 -0400
Re: about NULL as a parameter to a libc function Tim Rentsch <txr@alumni.caltech.edu> - 2012-01-24 22:13 -0800
Re: about NULL as a parameter to a libc function Ike Naar <ike@sverige.freeshell.org> - 2011-11-03 18:20 +0000
Re: about NULL as a parameter to a libc function Ike Naar <ike@sverige.freeshell.org> - 2011-11-03 18:34 +0000
Re: about NULL as a parameter to a libc function Kaz Kylheku <kaz@kylheku.com> - 2011-11-03 19:49 +0000
Re: about NULL as a parameter to a libc function James Kuyper <jameskuyper@verizon.net> - 2011-11-03 16:21 -0400
Re: about NULL as a parameter to a libc function Ike Naar <ike@iceland.freeshell.org> - 2011-11-03 22:19 +0000
Re: about NULL as a parameter to a libc function Tim Rentsch <txr@alumni.caltech.edu> - 2012-01-24 22:17 -0800
Re: about NULL as a parameter to a libc function Tim Rentsch <txr@alumni.caltech.edu> - 2012-01-24 21:19 -0800
Re: about NULL as a parameter to a libc function Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-10-28 14:26 +0100
Re: about NULL as a parameter to a libc function Joe Pfeiffer <pfeiffer@cs.nmsu.edu> - 2011-10-28 12:46 -0600
Re: about NULL as a parameter to a libc function Keith Thompson <kst-u@mib.org> - 2011-10-28 14:19 -0700
Re: about NULL as a parameter to a libc function Keith Thompson <kst-u@mib.org> - 2011-10-28 16:37 -0700
Re: about NULL as a parameter to a libc function James Kuyper <jameskuyper@verizon.net> - 2011-10-28 07:22 -0400
Re: about NULL as a parameter to a libc function Kenneth Brody <kenbrody@spamcop.net> - 2011-11-03 10:40 -0400
Re: about NULL as a parameter to a libc function Kaz Kylheku <kaz@kylheku.com> - 2011-11-03 15:10 +0000
Re: about NULL as a parameter to a libc function Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-11-04 03:03 +0000
Re: about NULL as a parameter to a libc function Eric Sosman <esosman@ieee-dot-org.invalid> - 2011-10-28 08:42 -0400
Re: about NULL as a parameter to a libc function "io_x" <a@b.c.invalid> - 2011-10-28 16:31 +0200
Re: about NULL as a parameter to a libc function "BartC" <bc@freeuk.com> - 2011-10-28 20:29 +0100
Re: about NULL as a parameter to a libc function Phil Carmody <thefatphil_demunged@yahoo.co.uk> - 2011-10-29 14:49 +0300
Re: about NULL as a parameter to a libc function Ike Naar <ike@sverige.freeshell.org> - 2011-10-29 13:41 +0000
Re: about NULL as a parameter to a libc function John Gordon <gordon@panix.com> - 2011-10-28 19:53 +0000
Re: about NULL as a parameter to a libc function "BartC" <bc@freeuk.com> - 2011-10-28 21:13 +0100
Re: about NULL as a parameter to a libc function John Gordon <gordon@panix.com> - 2011-10-28 20:33 +0000
Re: about NULL as a parameter to a libc function James Kuyper <jameskuyper@verizon.net> - 2011-10-28 16:56 -0400
Re: about NULL as a parameter to a libc function blp@cs.stanford.edu (Ben Pfaff) - 2011-10-28 14:30 -0700
Re: about NULL as a parameter to a libc function James Kuyper <jameskuyper@verizon.net> - 2011-10-28 16:45 -0400
Re: about NULL as a parameter to a libc function Keith Thompson <kst-u@mib.org> - 2011-10-28 15:35 -0700
Re: about NULL as a parameter to a libc function "BartC" <bc@freeuk.com> - 2011-10-29 13:00 +0100
Re: about NULL as a parameter to a libc function Keith Thompson <kst-u@mib.org> - 2011-10-29 11:26 -0700
Re: about NULL as a parameter to a libc function "BartC" <bc@freeuk.com> - 2011-10-29 20:24 +0100
Re: about NULL as a parameter to a libc function Keith Thompson <kst-u@mib.org> - 2011-10-29 14:03 -0700
Re: about NULL as a parameter to a libc function Nick Keighley <nick_keighley_nospam@hotmail.com> - 2011-10-29 07:30 -0700
Re: about NULL as a parameter to a libc function Kenneth Brody <kenbrody@spamcop.net> - 2011-11-03 11:26 -0400
Re: about NULL as a parameter to a libc function James Kuyper <jameskuyper@verizon.net> - 2011-11-03 12:59 -0400
Re: about NULL as a parameter to a libc function Keith Thompson <kst-u@mib.org> - 2011-11-03 13:42 -0700
Re: about NULL as a parameter to a libc function Kaz Kylheku <kaz@kylheku.com> - 2011-10-28 20:17 +0000
Re: about NULL as a parameter to a libc function Richard Damon <news.x.richarddamon@xoxy.net> - 2011-10-28 18:51 -0400
Re: about NULL as a parameter to a libc function Nobody <nobody@nowhere.com> - 2011-10-28 21:40 +0100
Re: about NULL as a parameter to a libc function James Kuyper <jameskuyper@verizon.net> - 2011-10-28 17:09 -0400
Re: about NULL as a parameter to a libc function Phil Carmody <thefatphil_demunged@yahoo.co.uk> - 2011-10-29 15:03 +0300
Re: about NULL as a parameter to a libc function James Kuyper <jameskuyper@verizon.net> - 2011-10-29 09:42 -0400
Re: about NULL as a parameter to a libc function Kaz Kylheku <kaz@kylheku.com> - 2011-10-28 21:18 +0000
Re: about NULL as a parameter to a libc function Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-10-28 23:30 +0100
Re: about NULL as a parameter to a libc function Keith Thompson <kst-u@mib.org> - 2011-10-28 15:37 -0700
Re: about NULL as a parameter to a libc function Kaz Kylheku <kaz@kylheku.com> - 2011-10-28 23:47 +0000
Re: about NULL as a parameter to a libc function Keith Thompson <kst-u@mib.org> - 2011-10-28 17:13 -0700
Re: about NULL as a parameter to a libc function Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-10-29 04:31 +0100
Re: about NULL as a parameter to a libc function Kaz Kylheku <kaz@kylheku.com> - 2011-10-29 05:42 +0000
Re: about NULL as a parameter to a libc function Seebs <usenet-nospam@seebs.net> - 2011-10-30 17:22 +0000
Re: about NULL as a parameter to a libc function Patrick Scheible <kkt@zipcon.net> - 2011-10-30 23:43 -0700
Re: about NULL as a parameter to a libc function Robert Wessel <robertwessel2@yahoo.com> - 2011-10-31 05:31 -0500
Re: about NULL as a parameter to a libc function Phil Carmody <thefatphil_demunged@yahoo.co.uk> - 2011-10-31 12:42 +0200
Re: about NULL as a parameter to a libc function Robert Wessel <robertwessel2@yahoo.com> - 2011-10-31 13:11 -0500
Re: about NULL as a parameter to a libc function Seebs <usenet-nospam@seebs.net> - 2011-10-31 17:18 +0000
Re: about NULL as a parameter to a libc function Nick Keighley <nick_keighley_nospam@hotmail.com> - 2011-10-29 07:32 -0700
Re: about NULL as a parameter to a libc function jacob navia <jacob@spamsink.net> - 2011-10-28 23:41 +0200
Re: about NULL as a parameter to a libc function Kaz Kylheku <kaz@kylheku.com> - 2011-10-28 22:42 +0000
Re: about NULL as a parameter to a libc function jacob navia <jacob@spamsink.net> - 2011-10-29 10:09 +0200
Re: about NULL as a parameter to a libc function Nobody <nobody@nowhere.com> - 2011-10-29 10:11 +0100
Re: about NULL as a parameter to a libc function Angel <angel+news@spamcop.net> - 2011-10-29 09:42 +0000
Re: about NULL as a parameter to a libc function jacob navia <jacob@spamsink.net> - 2011-10-29 16:17 +0200
Re: about NULL as a parameter to a libc function Nick Keighley <nick_keighley_nospam@hotmail.com> - 2011-10-29 07:39 -0700
Re: about NULL as a parameter to a libc function jacob navia <jacob@spamsink.net> - 2011-10-29 19:29 +0200
Re: about NULL as a parameter to a libc function "io_x" <a@b.c.invalid> - 2011-10-29 20:25 +0200
Re: about NULL as a parameter to a libc function Nick Keighley <nick_keighley_nospam@hotmail.com> - 2011-10-30 08:14 -0700
Re: about NULL as a parameter to a libc function ImpalerCore <jadill33@gmail.com> - 2011-10-31 18:30 -0700
Re: about NULL as a parameter to a libc function Tim Rentsch <txr@alumni.caltech.edu> - 2012-01-24 18:21 -0800
Re: about NULL as a parameter to a libc function Kenneth Brody <kenbrody@spamcop.net> - 2011-11-03 11:31 -0400
Re: about NULL as a parameter to a libc function Keith Thompson <kst-u@mib.org> - 2011-11-03 13:45 -0700
Re: about NULL as a parameter to a libc function Jonathan Leffler <jleffler@earthlink.net> - 2011-10-29 23:41 -0700
Re: about NULL as a parameter to a libc function James Kuyper <jameskuyper@verizon.net> - 2011-10-30 07:13 -0400
Page 4 of 6 — ← Prev page 1 2 3 [4] 5 6 Next page →
| From | blp@cs.stanford.edu (Ben Pfaff) |
|---|---|
| Date | 2011-10-28 14:30 -0700 |
| Message-ID | <87ty6s6bz9.fsf@blp.benpfaff.org> |
| In reply to | #12195 |
James Kuyper <jameskuyper@verizon.net> writes: > A more useful return value for memcpy(dest, src, count) would be > (void*)((char*)dest + count). A naive C-based implementation of memcpy() > calculates that value automaticly as a side effect of doing it's job; a > clever compiler might arrange, at no extra cost, for it to already be > residing in the same register used for returning small scalar values > from a function. The same might also be true even of more efficient > implementations using assembly language. > That value could be useful when doing a long series of memcpy() calls > into consecutive memory locations. A similar argument applies to several > of the str*() functions. However, it's too late now for changes like > that to the C standard library. There's a GNU extension named mempcpy() that has the return value semantics that you suggest might be useful for memcpy(). POSIX 2008 standardized a common C library extension called stpcpy(), that acts like strcpy() except that it returns a pointer to the null terminator byte written to the destination string. -- "To get the best out of this book, I strongly recommend that you read it." --Richard Heathfield
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Date | 2011-10-28 16:45 -0400 |
| Message-ID | <4EAB1459.6030604@verizon.net> |
| In reply to | #12190 |
On 10/28/2011 04:13 PM, BartC wrote: ... > When you use a function such as memcpy, you often have to check that each > operand is in fact not null: > > if (A && B && N) memcpy(A, B, N); Often? I just checked the most convenient body of code I had on hand, consisting of 278 source code files with a total of 107238 lines, and 4017043 bytes of code. A large fraction of that code was written by me. It contains 85 calls to memcpy(), and not a single instance where the call was controlled directly by an if() based upon A, B, or N. There were only two instances where the call was directly controlled by an if(), but the if tested something other condition entirely - it determined whether the data needed to be copied, not whether the pointers were non-null or the count non-zero. Much more common was the deliberate placement of the memcpy() call in a block that could only be entered if the relevant pointers were non-null and the count was non-zero; but that block existed for other reasons than making the memcpy() safe, so putting the memcpy() call into that block did not increase the number of conditions that needed to be tested. > memcpy(A, B, N); > > and know that no copying is done when any argument is null or zero? Having a > null source or destination is not necessarily an error (and if it is, you > check it conventionally). Given how rarely I need this feature, I prefer the current situation, where those who need it can implement it just by writing: if (A && B && N) memcpy(A, B, N); If they need to do it frequently, they can even make it a macro or an inline function.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2011-10-28 15:35 -0700 |
| Message-ID | <lnhb2slp7p.fsf@nuthaus.mib.org> |
| In reply to | #12190 |
"BartC" <bc@freeuk.com> writes:
> "John Gordon" <gordon@panix.com> wrote in message
> news:j8f16r$pgt$1@reader1.panix.com...
[...]
>> memcpy is doing you a favor by alerting you to a problem: the data did
>> not get copied.
Though it's not required to do so. The behavior is undefined; a seg
fault is not required.
> When you use a function such as memcpy, you often have to check that each
> operand is in fact not null:
>
> if (A && B && N) memcpy(A, B, N);
>
> when A, B, N are themselves arguments to your code, for example. Wouldn't it
> be a lot easier to just write:
>
> memcpy(A, B, N);
>
> and know that no copying is done when any argument is null or zero? Having a
> null source or destination is not necessarily an error (and if it is, you
> check it conventionally).
One could make exactly the same argument for a simple assignment
(without the N, of course). Perhaps it would be simpler to be able to
write:
*A = *B;
and have it quietly do nothing if either A or B is a null pointer. But
as others have said in parallel followups, when you're writing a
statement that copies data, you should generally have enough awareness
of the context to *know* that there's actually something to be copied.
Do you actually find yourself making such checks in your own code?
There are a nearly unlimited number of ways you can call memcpy()
incorrectly. You can try to copy too few or too many bytes. You can
pass invalid non-null pointers. You can reverse the first and second
arguments. You can pass perfectly valid pointers that just don't happen
to point to the objects you really wanted to copy.
The question is, would it really be worthwhile for memcpy() to detect
just a few kinds of errors (when other equally serious errors are
undetectable)?
How often would having memcpy() check for null pointers make it easier
to write correct code *in practice*?
[...]
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | "BartC" <bc@freeuk.com> |
|---|---|
| Date | 2011-10-29 13:00 +0100 |
| Message-ID | <j8gpuk$p58$1@dont-email.me> |
| In reply to | #12209 |
"Keith Thompson" <kst-u@mib.org> wrote in message news:lnhb2slp7p.fsf@nuthaus.mib.org... > "BartC" <bc@freeuk.com> writes: >>Wouldn't it be a lot easier to just write: >> >> memcpy(A, B, N); >> >> and know that no copying is done when any argument is null or zero? >> Having a >> null source or destination is not necessarily an error (and if it is, you >> check it conventionally). > > One could make exactly the same argument for a simple assignment > (without the N, of course). Perhaps it would be simpler to be able to > write: > > *A = *B; > > and have it quietly do nothing if either A or B is a null pointer. With a basic language statement like assignment, you wouldn't expect it to be backed up with logic to make sure operands are not null. And it can't be called remotely, where there would be no opportunity for the writer of the *A=*B to put in extra checks. A function (any function really, rather than just memcpy) is different; it can be called remotely, and it is easy to add checks, and to define specific behaviours. > as others have said in parallel followups, when you're writing a > statement that copies data, you should generally have enough awareness > of the context to *know* that there's actually something to be copied. > > Do you actually find yourself making such checks in your own code? Yes. Both when calling C functions (and often these are called from higher-level scripting languages, which use null for empty strings, and can crash when directly calling a C function), and when writing my own functions where the caller cannot quite be trusted 100%, and even then I might put checks in anyway as I don't know what other callers might do in future. Of course these are not always as performance-critical as memcpy() where there is less room for manoeuvre. I can understand that requiring extra checks means the compiler cannot, for example, optimise a 4-byte memcpy into a couple of inline instructions. -- Bartc
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2011-10-29 11:26 -0700 |
| Message-ID | <lnzkgjk626.fsf@nuthaus.mib.org> |
| In reply to | #12230 |
"BartC" <bc@freeuk.com> writes:
> "Keith Thompson" <kst-u@mib.org> wrote in message
> news:lnhb2slp7p.fsf@nuthaus.mib.org...
>> "BartC" <bc@freeuk.com> writes:
>>>Wouldn't it be a lot easier to just write:
>>>
>>> memcpy(A, B, N);
>>>
>>> and know that no copying is done when any argument is null or zero?
>>> Having a
>>> null source or destination is not necessarily an error (and if it is, you
>>> check it conventionally).
>>
>> One could make exactly the same argument for a simple assignment
>> (without the N, of course). Perhaps it would be simpler to be able to
>> write:
>>
>> *A = *B;
>>
>> and have it quietly do nothing if either A or B is a null pointer.
>
> With a basic language statement like assignment, you wouldn't expect it to
> be backed up with logic to make sure operands are not null. And it can't be
> called remotely, where there would be no opportunity for the writer of the
> *A=*B to put in extra checks.
>
> A function (any function really, rather than just memcpy) is different; it
> can be called remotely, and it is easy to add checks, and to define specific
> behaviours.
memcpy(), in a very real sense, is a basic language feature. Yes, it's
in the library rather than in the core language, but its performance is
just as important as the performance of an assignment.
And having memcpy() check for null pointers and do nothing makes certain
errors *more difficult to detect*. If I write
memcpy(target, source, size);
and either target or source happens to be a null pointer, it's almost
certainly because I made a mistake. A memcpy() that hides that mistake
from me isn't doing me any favors; it's by no means certain that doing
nothing is the correct behavior that will "fix" the bug.
>> as others have said in parallel followups, when you're writing a
>> statement that copies data, you should generally have enough awareness
>> of the context to *know* that there's actually something to be copied.
>>
>> Do you actually find yourself making such checks in your own code?
>
> Yes. Both when calling C functions (and often these are called from
> higher-level scripting languages, which use null for empty strings, and can
> crash when directly calling a C function), and when writing my own functions
> where the caller cannot quite be trusted 100%, and even then I might put
> checks in anyway as I don't know what other callers might do in future.
Are these scripting languages of your own design? Perhaps using null
for empty strings wasn't the best choice. Is there a way to represent
an empty string using a non-null pointer? If so, do you really gain
much benefit from having two distinct representations for the same
thing? You'd have to do extra checks on almost every string operation.
Perhaps you have a good reason for doing it that way -- but then you
have to expect some overhead.
As for untrusted callers, when you check for an error condition, you
have to know how to handle it. How do you know that the way you handle
it (say, doing nothing for a null pointer) is the correct behavior?
> Of course these are not always as performance-critical as memcpy() where
> there is less room for manoeuvre. I can understand that requiring extra
> checks means the compiler cannot, for example, optimise a 4-byte memcpy into
> a couple of inline instructions.
Welcome to C.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | "BartC" <bc@freeuk.com> |
|---|---|
| Date | 2011-10-29 20:24 +0100 |
| Message-ID | <j8hjub$q7d$1@dont-email.me> |
| In reply to | #12253 |
"Keith Thompson" <kst-u@mib.org> wrote in message news:lnzkgjk626.fsf@nuthaus.mib.org... > "BartC" <bc@freeuk.com> writes: >> With a basic language statement like assignment, you wouldn't expect it >> to >> be backed up with logic to make sure operands are not null. >> A function (any function really, rather than just memcpy) is different; > memcpy(), in a very real sense, is a basic language feature. Yes, it's > in the library rather than in the core language, but its performance is > just as important as the performance of an assignment. > > And having memcpy() check for null pointers and do nothing makes certain > errors *more difficult to detect*. If I write > > memcpy(target, source, size); > > and either target or source happens to be a null pointer, it's almost > certainly because I made a mistake. If size is zero, that's quite likely to be a mistake too. Yet the standard defines the behaviour in that case. (I've been looking at the Python implementation code; checking for size being zero is the most common check before calling memcpy(), even though it is not actually needed. Checks for destination or source being null are rarer.) > A memcpy() that hides that mistake > from me isn't doing me any favors; it's by no means certain that doing > nothing is the correct behavior that will "fix" the bug. Letting some code deliberately crash seems a rather drastic way of telling you something is wrong! And not crashing doesn't mean nothing else is wrong. >> Yes. Both when calling C functions (and often these are called from >> higher-level scripting languages, which use null for empty strings, and >> can >> crash when directly calling a C function), > Are these scripting languages of your own design? Perhaps using null > for empty strings wasn't the best choice. Is there a way to represent > an empty string using a non-null pointer? (I use counted strings, which also have a tag saying if it's a string or not. Having a length=0 and ptr=0 was the simplest way of doing things. It's not a big deal, I need to do extra fixing-up of string arguments. (And that reminds me I'm planning to do away with zero-terminators too, a bigger headache when calling C and Windows functions.)) > As for untrusted callers, when you check for an error condition, you > have to know how to handle it. How do you know that the way you handle > it (say, doing nothing for a null pointer) is the correct behavior? Sometimes I start writing a function before fully documenting it or knowing exactly how it will be used, or whether a null parameter is even likely. It's simplest to just put checks for null right from the start. Usually it doesn't hurt. If the value *shouldn't* have been null, then I will find out when the program doesn't do what I want! -- Bartc
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2011-10-29 14:03 -0700 |
| Message-ID | <lnehxvjysb.fsf@nuthaus.mib.org> |
| In reply to | #12259 |
"BartC" <bc@freeuk.com> writes:
> "Keith Thompson" <kst-u@mib.org> wrote in message
> news:lnzkgjk626.fsf@nuthaus.mib.org...
>> "BartC" <bc@freeuk.com> writes:
>
>>> With a basic language statement like assignment, you wouldn't expect it
>>> to
>>> be backed up with logic to make sure operands are not null.
>
>>> A function (any function really, rather than just memcpy) is different;
>
>> memcpy(), in a very real sense, is a basic language feature. Yes, it's
>> in the library rather than in the core language, but its performance is
>> just as important as the performance of an assignment.
>>
>> And having memcpy() check for null pointers and do nothing makes certain
>> errors *more difficult to detect*. If I write
>>
>> memcpy(target, source, size);
>>
>> and either target or source happens to be a null pointer, it's almost
>> certainly because I made a mistake.
>
> If size is zero, that's quite likely to be a mistake too. Yet the standard
> defines the behaviour in that case. (I've been looking at the Python
> implementation code; checking for size being zero is the most common check
> before calling memcpy(), even though it is not actually needed. Checks for
> destination or source being null are rarer.)
A size of zero isn't nearly as likely to be a mistake as a null
pointer. For example, suppose you have an array of (whatever) and
a count of how many elements of the array are currently meaningful.
It makes sense to use memcpy() to copy only the meaningful elements.
The fact that the behavior for size==0 is well defined means you
don't need to code that as a special case.
If you insist on treating a null pointer as if it were a pointer to
an empty (whatever), you can certainly do that -- but don't expect
memcpy() to have special-case code to check for null pointers just
so you don't have to.
I don't think anybody has claimed that the C standard library is a model
of consistency. It's evolved over the years from earlier libraries,
some of them independently developed, many of them optimized for much
smaller and slower systems. But I personally find the way memcpy() is
defined to be reasonable, and I think most other C programmers do as
well. (If you're saying that you don't like the way C is defined,
you're certainly not alone.)
>> A memcpy() that hides that mistake
>> from me isn't doing me any favors; it's by no means certain that doing
>> nothing is the correct behavior that will "fix" the bug.
>
> Letting some code deliberately crash seems a rather drastic way of telling
> you something is wrong! And not crashing doesn't mean nothing else is wrong.
Letting code deliberately crash is intended to tell *the developer*
that something is wrong. It's not just a random occurrence;
there's a lot of carefully crafted code in your operating system
that's designed to cause, handle, and report crashes.
[...]
> Sometimes I start writing a function before fully documenting it or knowing
> exactly how it will be used, or whether a null parameter is even likely.
> It's simplest to just put checks for null right from the start. Usually it
> doesn't hurt. If the value *shouldn't* have been null, then I will find out
> when the program doesn't do what I want!
Will you *always* find out? Not all bugs are detected when they should
be. If my code is buggy, I'd much rather have it crash early than
quietly behave in some way other than what I intended.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | Nick Keighley <nick_keighley_nospam@hotmail.com> |
|---|---|
| Date | 2011-10-29 07:30 -0700 |
| Message-ID | <efa9c972-ccd3-4c82-936c-35702fad41e7@o15g2000yqj.googlegroups.com> |
| In reply to | #12190 |
On Oct 28, 9:13 pm, "BartC" <b...@freeuk.com> wrote: > "John Gordon" <gor...@panix.com> wrote in message > > news:j8f16r$pgt$1@reader1.panix.com... > > > > > > > In <14abde31-4573-45e7-bdaf-eb70b2274...@z28g2000pro.googlegroups.com> > > gaoqiang <gaoqiangs...@gmail.com> writes: > > >> a good function should deal with unwanted parameters. > >> why memcpy,strcmp .etc ,these libc functions, do not > >> accept NULL pointer ? called with NULL, just get segment > >> fault. for efficiency ? > > > Let's take your example of memcpy. > > > The purpose of memcpy is to copy bytes from one memory location to > > another. > > > If one of those locations is NULL, memcpy can't do anything useful. > > You can't copy bytes to or from a NULL location. > > memcpy is doing you a favor by alerting you to a problem: the data did > > not get copied. > > When you use a function such as memcpy, you often have to check that each > operand is in fact not null: > > if (A && B && N) memcpy(A, B, N); > > when A, B, N are themselves arguments to your code, for example. Wouldn't it > be a lot easier to just write: > > memcpy(A, B, N); > > and know that no copying is done when any argument is null or zero? Having a > null source or destination is not necessarily an error (and if it is, you > check it conventionally). > > > If memcpy just returned without raising an exception, you wouldn't have > > any way of knowing that the bytes didn't get copied. > > What value does memcpy() return? Couldn't it have returned the number of > bytes actually copied? the first parameter > Anyway there's a million ways a program can silently go wrong; A, B and N > might not be zero, but how do we know they are correct? > > Having a program deliberately crash is a crude way of detecting some classes > of error. > > -- > Bartc- Hide quoted text - > > - Show quoted text -
[toc] | [prev] | [next] | [standalone]
| From | Kenneth Brody <kenbrody@spamcop.net> |
|---|---|
| Date | 2011-11-03 11:26 -0400 |
| Message-ID | <XLKdnaK_MJsILy_TnZ2dnUVZ_gWdnZ2d@bestweb.net> |
| In reply to | #12190 |
On 10/28/2011 4:13 PM, BartC wrote:
> "John Gordon" <gordon@panix.com> wrote in message
[...]
>> Let's take your example of memcpy.
>>
>> The purpose of memcpy is to copy bytes from one memory location to
>> another.
>>
>> If one of those locations is NULL, memcpy can't do anything useful.
>> You can't copy bytes to or from a NULL location.
>
>> memcpy is doing you a favor by alerting you to a problem: the data did
>> not get copied.
>
> When you use a function such as memcpy, you often have to check that each
> operand is in fact not null:
>
> if (A && B && N) memcpy(A, B, N);
>
> when A, B, N are themselves arguments to your code, for example. Wouldn't it
> be a lot easier to just write:
>
> memcpy(A, B, N);
>
> and know that no copying is done when any argument is null or zero? Having a
> null source or destination is not necessarily an error (and if it is, you
> check it conventionally).
So, memcpy() should lie to you? When you say "copy 50 bytes from NULL to
foo", it should just do nothing?
While it could be argued that, if N is zero, a NULL pointer should be
"legal", what about non-zero-length requests?
What you are saying is that memcpy() should have the overhead of checking
every call to it, even if the caller guarantees that the pointers are valid,
rather than having the caller be responsible to check in the cases where
there might be a NULL pointer. And, if it's possible that one of the
pointers could be zero, shouldn't it be up to the caller to decide how to
handle it?
>> If memcpy just returned without raising an exception, you wouldn't have
>> any way of knowing that the bytes didn't get copied.
>
> What value does memcpy() return? Couldn't it have returned the number of
> bytes actually copied?
memcpy() returns the first parameter. In ye olde days, this was probably to
allow the buffer to be "efficiently" passed to some other function to be
handled. (Besides, the only other "reasonable" return would be nothing at all.)
How would returning "the number of bytes actually copied" be useful? It's
guaranteed (assuming no UB) to the the number of bytes passed to it.
> Anyway there's a million ways a program can silently go wrong; A, B and N
> might not be zero, but how do we know they are correct?
>
> Having a program deliberately crash is a crude way of detecting some classes
> of error.
"Deliberately crash" is a bit misleading. The crash, on those systems which
do crash, is a side effect of invoking UB. It's not like the implementation
has:
if ( s1 == NULL ) CrashProgram();
--
Kenneth Brody
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Date | 2011-11-03 12:59 -0400 |
| Message-ID | <4EB2C86D.2070907@verizon.net> |
| In reply to | #12592 |
On 11/03/2011 11:26 AM, Kenneth Brody wrote: ... > memcpy() returns the first parameter. In ye olde days, this was probably to > allow the buffer to be "efficiently" passed to some other function to be > handled. (Besides, the only other "reasonable" return would be nothing at all.) It would have been marginally more useful for memcpy(dest, source, count) to have returned either (void*)((char*)dest+count) or (void*)((char*)source+count). > How would returning "the number of bytes actually copied" be useful? It's > guaranteed (assuming no UB) to the the number of bytes passed to it. He's suggesting that it no longer be UB if one or both of the pointer arguments is null, in which case returning 0 as the number of bytes copied would have some use. Not a lot, but some.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2011-11-03 13:42 -0700 |
| Message-ID | <lnk47hgcp0.fsf@nuthaus.mib.org> |
| In reply to | #12592 |
Kenneth Brody <kenbrody@spamcop.net> writes:
> On 10/28/2011 4:13 PM, BartC wrote:
[...]
>> Anyway there's a million ways a program can silently go wrong; A, B and N
>> might not be zero, but how do we know they are correct?
>>
>> Having a program deliberately crash is a crude way of detecting some classes
>> of error.
>
> "Deliberately crash" is a bit misleading. The crash, on those systems which
> do crash, is a side effect of invoking UB. It's not like the implementation
> has:
>
> if ( s1 == NULL ) CrashProgram();
Actually, on some level within the operating system, there's code
that does something very much like that. A segmentation fault,
for example, is not just a random occurrence; substantial effort
went into designing the OS (and probably the hardware) so that
invalid memory accesses result in well-defined behavior. (That is,
well-defined by the OS, not by C.)
The point is (a) to alert the developer to the problem, so the code
can be corrected to avoid it, and (b) to prevent the program from
continuing to execute in an invalid state.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | Kaz Kylheku <kaz@kylheku.com> |
|---|---|
| Date | 2011-10-28 20:17 +0000 |
| Message-ID | <20111028161052.465@kylheku.com> |
| In reply to | #12167 |
On 2011-10-28, gaoqiang <gaoqiangscut@gmail.com> wrote: > a good function should deal with unwanted parameters. > > why memcpy,strcmp .etc ,these libc functions, do not > > accept NULL pointer ? called with NULL, just get segment This means that the funtions actually do accept the pointer and try to do what they are told: move memory to or from the null pointer! It's your virtual memory managment (CPU feature + operating system) that doesn't like the null pointer. If you dereference a null pointer to access memory, you will get this segfault, no matter what syntax or function you use. > fault. for efficiency ? No. It would be more efficient to just accept null inside the memcpy function (as is already the case in your implementation!) AND also not have the virtual memory management which catches the fault. Trapping null to a segfault requires extra circuitry which complicates the processor and introduces performance penalties (which are difficult to analyze, since they have to do with the access pattern to pages, and the replacement strategy of entries the translation cache.)
[toc] | [prev] | [next] | [standalone]
| From | Richard Damon <news.x.richarddamon@xoxy.net> |
|---|---|
| Date | 2011-10-28 18:51 -0400 |
| Message-ID | <j8fbkr$qbo$1@dont-email.me> |
| In reply to | #12191 |
On 10/28/11 4:17 PM, Kaz Kylheku wrote: > > Trapping null to a segfault requires extra circuitry which complicates the > processor and introduces performance penalties (which are difficult to analyze, > since they have to do with the access pattern to pages, and the replacement > strategy of entries the translation cache.) The trapping of the Null pointer come out basically for free from the segment/virtual memory processing that allows those computers to run multiple programs with virtual memory. At most it causes a single if in the OS to see if the access to unmapped page fault occurs for a page that should be added to the programs address space or not.
[toc] | [prev] | [next] | [standalone]
| From | Nobody <nobody@nowhere.com> |
|---|---|
| Date | 2011-10-28 21:40 +0100 |
| Message-ID | <pan.2011.10.28.20.40.48.528000@nowhere.com> |
| In reply to | #12167 |
On Fri, 28 Oct 2011 01:49:45 -0700, gaoqiang wrote:
> why memcpy,strcmp .etc ,these libc functions, do not
> accept NULL pointer ? called with NULL, just get segment
> fault. for efficiency ?
What would you expect strcmp("", NULL) to return?
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Date | 2011-10-28 17:09 -0400 |
| Message-ID | <4EAB1A0E.1050607@verizon.net> |
| In reply to | #12193 |
On 10/28/2011 04:40 PM, Nobody wrote:
> On Fri, 28 Oct 2011 01:49:45 -0700, gaoqiang wrote:
>
>> why memcpy,strcmp .etc ,these libc functions, do not
>> accept NULL pointer ? called with NULL, just get segment
>> fault. for efficiency ?
>
> What would you expect strcmp("", NULL) to return?
I wouldn't recommend such a change, but if it were made, it's often not
that difficult to come up with reasonable definitions of the behavior in
the cases that are currently undefined. In this case, the following
would be one plausible approach:
int strcmp(const char *s1, const char *s2)
{
if(s1 && s2)
return old_strcmp(s1, s2);
return !!s1 - !!s2;
}
[toc] | [prev] | [next] | [standalone]
| From | Phil Carmody <thefatphil_demunged@yahoo.co.uk> |
|---|---|
| Date | 2011-10-29 15:03 +0300 |
| Message-ID | <877h3om2cb.fsf@bazspaz.fatphil.org> |
| In reply to | #12196 |
James Kuyper <jameskuyper@verizon.net> writes:
> On 10/28/2011 04:40 PM, Nobody wrote:
> > On Fri, 28 Oct 2011 01:49:45 -0700, gaoqiang wrote:
> >
> >> why memcpy,strcmp .etc ,these libc functions, do not
> >> accept NULL pointer ? called with NULL, just get segment
> >> fault. for efficiency ?
> >
> > What would you expect strcmp("", NULL) to return?
>
> I wouldn't recommend such a change, but if it were made, it's often not
> that difficult to come up with reasonable definitions of the behavior in
> the cases that are currently undefined. In this case, the following
> would be one plausible approach:
>
> int strcmp(const char *s1, const char *s2)
> {
> if(s1 && s2)
> return old_strcmp(s1, s2);
> return !!s1 - !!s2;
Why not !s2 - !s1 ?
> }
--
Unix is simple. It just takes a genius to understand its simplicity
-- Dennis Ritchie (1941-2011), Unix Co-Creator
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Date | 2011-10-29 09:42 -0400 |
| Message-ID | <j8gvro$qmk$1@dont-email.me> |
| In reply to | #12231 |
On 10/29/2011 08:03 AM, Phil Carmody wrote:
> James Kuyper <jameskuyper@verizon.net> writes:
...
>> I wouldn't recommend such a change, but if it were made, it's often not
>> that difficult to come up with reasonable definitions of the behavior in
>> the cases that are currently undefined. In this case, the following
>> would be one plausible approach:
>>
>> int strcmp(const char *s1, const char *s2)
>> {
>> if(s1 && s2)
>> return old_strcmp(s1, s2);
>> return !!s1 - !!s2;
>
> Why not !s2 - !s1 ?
Because I didn't think of it. :-(
--
James Kuyper
[toc] | [prev] | [next] | [standalone]
| From | Kaz Kylheku <kaz@kylheku.com> |
|---|---|
| Date | 2011-10-28 21:18 +0000 |
| Message-ID | <20111028170437.700@kylheku.com> |
| In reply to | #12193 |
On 2011-10-28, Nobody <nobody@nowhere.com> wrote:
> On Fri, 28 Oct 2011 01:49:45 -0700, gaoqiang wrote:
>
>> why memcpy,strcmp .etc ,these libc functions, do not
>> accept NULL pointer ? called with NULL, just get segment
>> fault. for efficiency ?
>
> What would you expect strcmp("", NULL) to return?
If this combination of inputs were to be defined, I would expect the null
pointer not to compare equal to any string, since it isn't one.
The remaining question, then, is where the null pointer lands in a
lexicographic comparison against strings. I would place it ahead of
strings, so that if you a null mixed up among a set of strings, it
makes itself obvious by taking the top position in a sorted list.
Furthermore, strcmp(NULL, NULL) ought return zero, since it is astonishing
if a thing is not deemed equal to itself (reflexive property of the equivalence
relation).
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2011-10-28 23:30 +0100 |
| Message-ID | <0.f97027fafda2f908799f.20111028233048BST.8762j8lpev.fsf@bsb.me.uk> |
| In reply to | #12199 |
Kaz Kylheku <kaz@kylheku.com> writes: <snip> > Furthermore, strcmp(NULL, NULL) ought return zero, since it is > astonishing if a thing is not deemed equal to itself (reflexive > property of the equivalence relation). There is a fine tradition that says otherwise. Even in C, x == x is not always 1 (e.g. when x is NaN). -- Ben.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2011-10-28 15:37 -0700 |
| Message-ID | <lnd3dglp35.fsf@nuthaus.mib.org> |
| In reply to | #12199 |
Kaz Kylheku <kaz@kylheku.com> writes:
> On 2011-10-28, Nobody <nobody@nowhere.com> wrote:
>> On Fri, 28 Oct 2011 01:49:45 -0700, gaoqiang wrote:
>>
>>> why memcpy,strcmp .etc ,these libc functions, do not
>>> accept NULL pointer ? called with NULL, just get segment
>>> fault. for efficiency ?
>>
>> What would you expect strcmp("", NULL) to return?
>
> If this combination of inputs were to be defined, I would expect the null
> pointer not to compare equal to any string, since it isn't one.
>
> The remaining question, then, is where the null pointer lands in a
> lexicographic comparison against strings. I would place it ahead of
> strings, so that if you a null mixed up among a set of strings, it
> makes itself obvious by taking the top position in a sorted list.
>
> Furthermore, strcmp(NULL, NULL) ought return zero, since it is
> astonishing if a thing is not deemed equal to itself (reflexive
> property of the equivalence relation).
One could make a case that a null pointer is Not A String, in a similar
sense to the way NaN is Not A Number. NaN compares unequal to itself.
Defining *some* consistent set of behavior wouldn't be difficult.
Getting everyone to agree that it's the right definition would be
impossible. (And leaving things the way they are is, IMHO, the best
approach.)
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
Page 4 of 6 — ← Prev page 1 2 3 [4] 5 6 Next page →
Back to top | Article view | comp.lang.c
csiph-web