Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #94806 > unrolled thread
| Started by | Noob <root@127.0.0.1> |
|---|---|
| First post | 2016-10-13 12:42 +0200 |
| Last post | 2016-10-22 16:33 -0700 |
| Articles | 20 on this page of 100 — 20 participants |
Back to article view | Back to comp.lang.c
UB of memcpy(NULL, NULL, 0) Noob <root@127.0.0.1> - 2016-10-13 12:42 +0200
Re: UB of memcpy(NULL, NULL, 0) Richard Heathfield <rjh@cpax.org.uk> - 2016-10-13 11:55 +0100
Re: UB of memcpy(NULL, NULL, 0) Noob <root@127.0.0.1> - 2016-10-13 13:09 +0200
Re: UB of memcpy(NULL, NULL, 0) Richard Heathfield <rjh@cpax.org.uk> - 2016-10-13 12:22 +0100
Re: UB of memcpy(NULL, NULL, 0) supercat@casperkitty.com - 2016-10-13 12:22 -0700
Re: UB of memcpy(NULL, NULL, 0) "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-10-13 12:32 -0700
Re: UB of memcpy(NULL, NULL, 0) "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-10-13 12:34 -0700
Re: UB of memcpy(NULL, NULL, 0) Joe Pfeiffer <pfeiffer@cs.nmsu.edu> - 2016-10-13 08:24 -0600
Re: UB of memcpy(NULL, NULL, 0) Richard Heathfield <rjh@cpax.org.uk> - 2016-10-13 16:22 +0100
Re: UB of memcpy(NULL, NULL, 0) Noob <root@127.0.0.1> - 2016-10-13 17:49 +0200
Re: UB of memcpy(NULL, NULL, 0) Joe Pfeiffer <pfeiffer@cs.nmsu.edu> - 2016-10-13 12:02 -0600
Re: UB of memcpy(NULL, NULL, 0) Lőrinczy Zsigmond <nospam@for.me> - 2016-10-15 20:56 +0200
Re: UB of memcpy(NULL, NULL, 0) supercat@casperkitty.com - 2016-10-15 12:52 -0700
Re: UB of memcpy(NULL, NULL, 0) "James R. Kuyper" <jameskuyper@verizon.net> - 2016-10-15 15:55 -0400
Re: UB of memcpy(NULL, NULL, 0) Keith Thompson <kst-u@mib.org> - 2016-10-15 13:41 -0700
Re: UB of memcpy(NULL, NULL, 0) Lőrinczy Zsigmond <nospam@for.me> - 2016-10-16 11:17 +0200
Re: UB of memcpy(NULL, NULL, 0) Richard Heathfield <rjh@cpax.org.uk> - 2016-10-16 10:26 +0100
Re: UB of memcpy(NULL, NULL, 0) raltbos@xs4all.nl (Richard Bos) - 2016-10-16 09:55 +0000
Re: UB of memcpy(NULL, NULL, 0) Jerry Stuckle <jstucklex@attglobal.net> - 2016-10-16 08:44 -0400
Re: UB of memcpy(NULL, NULL, 0) David Brown <david.brown@hesbynett.no> - 2016-10-17 10:06 +0200
Re: UB of memcpy(NULL, NULL, 0) Jerry Stuckle <jstucklex@attglobal.net> - 2016-10-17 09:06 -0400
Re: UB of memcpy(NULL, NULL, 0) David Brown <david.brown@hesbynett.no> - 2016-10-17 16:29 +0200
Re: UB of memcpy(NULL, NULL, 0) Jerry Stuckle <jstucklex@attglobal.net> - 2016-10-17 17:05 -0400
Re: UB of memcpy(NULL, NULL, 0) David Brown <david.brown@hesbynett.no> - 2016-10-18 11:19 +0200
Re: UB of memcpy(NULL, NULL, 0) supercat@casperkitty.com - 2016-10-18 08:04 -0700
Re: UB of memcpy(NULL, NULL, 0) Jerry Stuckle <jstucklex@attglobal.net> - 2016-10-18 16:27 -0400
Re: UB of memcpy(NULL, NULL, 0) supercat@casperkitty.com - 2016-10-17 08:59 -0700
Re: UB of memcpy(NULL, NULL, 0) Keith Thompson <kst-u@mib.org> - 2016-10-17 11:21 -0700
Re: UB of memcpy(NULL, NULL, 0) supercat@casperkitty.com - 2016-10-17 13:42 -0700
Re: UB of memcpy(NULL, NULL, 0) Keith Thompson <kst-u@mib.org> - 2016-10-17 14:46 -0700
Re: UB of memcpy(NULL, NULL, 0) supercat@casperkitty.com - 2016-10-17 15:52 -0700
Re: UB of memcpy(NULL, NULL, 0) Keith Thompson <kst-u@mib.org> - 2016-10-17 16:43 -0700
Re: UB of memcpy(NULL, NULL, 0) supercat@casperkitty.com - 2016-10-18 08:00 -0700
Re: UB of memcpy(NULL, NULL, 0) Keith Thompson <kst-u@mib.org> - 2016-10-18 09:14 -0700
Re: UB of memcpy(NULL, NULL, 0) supercat@casperkitty.com - 2016-10-18 09:43 -0700
Re: UB of memcpy(NULL, NULL, 0) Keith Thompson <kst-u@mib.org> - 2016-10-18 11:31 -0700
Re: UB of memcpy(NULL, NULL, 0) supercat@casperkitty.com - 2016-10-18 12:49 -0700
Re: UB of memcpy(NULL, NULL, 0) Keith Thompson <kst-u@mib.org> - 2016-10-18 12:03 -0700
Re: UB of memcpy(NULL, NULL, 0) Jerry Stuckle <jstucklex@attglobal.net> - 2016-10-17 17:06 -0400
Re: UB of memcpy(NULL, NULL, 0) supercat@casperkitty.com - 2016-10-17 14:55 -0700
Re: UB of memcpy(NULL, NULL, 0) Keith Thompson <kst-u@mib.org> - 2016-10-16 11:23 -0700
Re: UB of memcpy(NULL, NULL, 0) supercat@casperkitty.com - 2016-10-17 08:49 -0700
Re: UB of memcpy(NULL, NULL, 0) raltbos@xs4all.nl (Richard Bos) - 2016-10-18 16:54 +0000
Re: UB of memcpy(NULL, NULL, 0) supercat@casperkitty.com - 2016-10-18 11:09 -0700
Re: UB of memcpy(NULL, NULL, 0) raltbos@xs4all.nl (Richard Bos) - 2016-10-23 13:24 +0000
Re: UB of memcpy(NULL, NULL, 0) supercat@casperkitty.com - 2016-10-24 09:28 -0700
Re: UB of memcpy(NULL, NULL, 0) <william@wilbur.25thandClement.com> - 2016-10-29 11:32 -0700
Re: UB of memcpy(NULL, NULL, 0) supercat@casperkitty.com - 2016-10-29 14:12 -0700
Re: UB of memcpy(NULL, NULL, 0) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-10-15 22:00 +0100
Re: UB of memcpy(NULL, NULL, 0) Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-10-16 02:51 -0700
Re: UB of memcpy(NULL, NULL, 0) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-10-16 11:20 +0100
Re: UB of memcpy(NULL, NULL, 0) Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-10-16 04:14 -0700
Re: UB of memcpy(NULL, NULL, 0) BartC <bc@freeuk.com> - 2016-10-16 12:22 +0100
Re: UB of memcpy(NULL, NULL, 0) Richard Heathfield <rjh@cpax.org.uk> - 2016-10-16 13:01 +0100
Re: UB of memcpy(NULL, NULL, 0) Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-10-16 05:29 -0700
Re: UB of memcpy(NULL, NULL, 0) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-10-16 20:47 +0100
Re: UB of memcpy(NULL, NULL, 0) Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-10-17 02:08 -0700
Re: UB of memcpy(NULL, NULL, 0) David Brown <david.brown@hesbynett.no> - 2016-10-17 10:24 +0200
Re: UB of memcpy(NULL, NULL, 0) Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-10-17 08:05 -0700
Re: UB of memcpy(NULL, NULL, 0) David Brown <david.brown@hesbynett.no> - 2016-10-17 17:25 +0200
Re: UB of memcpy(NULL, NULL, 0) Lőrinczy Zsigmond <nospam@for.me> - 2016-10-17 17:08 +0200
Re: UB of memcpy(NULL, NULL, 0) Lorinczy Zsigmond <zsiga@nospam.for.me> - 2016-10-21 12:46 +0200
Re: UB of memcpy(NULL, NULL, 0) supercat@casperkitty.com - 2016-10-21 08:06 -0700
Re: UB of memcpy(NULL, NULL, 0) Lőrinczy Zsigmond <nospam@for.me> - 2016-10-21 18:30 +0200
Re: UB of memcpy(NULL, NULL, 0) supercat@casperkitty.com - 2016-10-21 09:34 -0700
Re: UB of memcpy(NULL, NULL, 0) Lőrinczy Zsigmond <nospam@for.me> - 2016-10-22 07:42 +0200
Re: UB of memcpy(NULL, NULL, 0) James Kuyper <jameskuyper@verizon.net> - 2016-10-22 10:31 -0400
Re: UB of memcpy(NULL, NULL, 0) Lőrinczy Zsigmond <nospam@for.me> - 2016-10-22 17:49 +0200
Re: UB of memcpy(NULL, NULL, 0) Tim Rentsch <txr@alumni.caltech.edu> - 2016-10-22 13:43 -0700
Re: UB of memcpy(NULL, NULL, 0) Lőrinczy Zsigmond <nospam@for.me> - 2016-10-23 07:47 +0200
Re: UB of memcpy(NULL, NULL, 0) "James R. Kuyper" <jameskuyper@verizon.net> - 2016-10-23 11:07 -0400
Re: UB of memcpy(NULL, NULL, 0) Lőrinczy Zsigmond <nospam@for.me> - 2016-10-23 17:45 +0200
Re: UB of memcpy(NULL, NULL, 0) "James R. Kuyper" <jameskuyper@verizon.net> - 2016-10-23 12:16 -0400
Re: UB of memcpy(NULL, NULL, 0) supercat@casperkitty.com - 2016-10-24 07:38 -0700
Re: UB of memcpy(NULL, NULL, 0) Keith Thompson <kst-u@mib.org> - 2016-10-24 08:38 -0700
Re: UB of memcpy(NULL, NULL, 0) supercat@casperkitty.com - 2016-10-24 09:44 -0700
Re: UB of memcpy(NULL, NULL, 0) Keith Thompson <kst-u@mib.org> - 2016-10-23 12:22 -0700
Re: UB of memcpy(NULL, NULL, 0) Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-10-23 13:37 -0700
Re: UB of memcpy(NULL, NULL, 0) Keith Thompson <kst-u@mib.org> - 2016-10-23 14:15 -0700
Re: UB of memcpy(NULL, NULL, 0) Ike Naar <ike@iceland.freeshell.org> - 2016-10-24 06:11 +0000
Re: UB of memcpy(NULL, NULL, 0) Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-10-24 00:58 -0700
Re: UB of memcpy(NULL, NULL, 0) Tim Rentsch <txr@alumni.caltech.edu> - 2016-10-23 14:07 -0700
Re: UB of memcpy(NULL, NULL, 0) supercat@casperkitty.com - 2016-10-24 07:48 -0700
Re: UB of memcpy(NULL, NULL, 0) Keith Thompson <kst-u@mib.org> - 2016-10-24 08:40 -0700
Re: UB of memcpy(NULL, NULL, 0) supercat@casperkitty.com - 2016-10-24 10:03 -0700
Re: UB of memcpy(NULL, NULL, 0) Keith Thompson <kst-u@mib.org> - 2016-10-24 12:06 -0700
Re: UB of memcpy(NULL, NULL, 0) supercat@casperkitty.com - 2016-10-24 13:36 -0700
Re: UB of memcpy(NULL, NULL, 0) Keith Thompson <kst-u@mib.org> - 2016-10-24 13:57 -0700
Re: UB of memcpy(NULL, NULL, 0) Tim Rentsch <txr@alumni.caltech.edu> - 2016-10-24 14:16 -0700
Re: UB of memcpy(NULL, NULL, 0) supercat@casperkitty.com - 2016-10-24 17:23 -0700
Re: UB of memcpy(NULL, NULL, 0) Tim Rentsch <txr@alumni.caltech.edu> - 2016-10-25 07:57 -0700
Re: UB of memcpy(NULL, NULL, 0) James Kuyper <jameskuyper@verizon.net> - 2016-10-22 18:23 -0400
Re: UB of memcpy(NULL, NULL, 0) "James R. Kuyper" <jameskuyper@verizon.net> - 2016-10-23 10:44 -0400
Re: UB of memcpy(NULL, NULL, 0) Richard Heathfield <rjh@cpax.org.uk> - 2016-10-23 16:24 +0100
Re: Verbing Noob <root@127.0.0.1> - 2016-10-23 18:02 +0200
Re: UB of memcpy(NULL, NULL, 0) raltbos@xs4all.nl (Richard Bos) - 2016-10-23 13:26 +0000
Re: UB of memcpy(NULL, NULL, 0) Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-10-23 07:40 -0700
Re: UB of memcpy(NULL, NULL, 0) asetofsymbols@gmail.com - 2016-10-21 23:56 -0700
Re: UB of memcpy(NULL, NULL, 0) Lőrinczy Zsigmond <nospam@for.me> - 2016-10-22 12:21 +0200
Re: UB of memcpy(NULL, NULL, 0) Keith Thompson <kst-u@mib.org> - 2016-10-22 16:33 -0700
Page 1 of 5 [1] 2 3 4 5 Next page →
| From | Noob <root@127.0.0.1> |
|---|---|
| Date | 2016-10-13 12:42 +0200 |
| Subject | UB of memcpy(NULL, NULL, 0) |
| Message-ID | <ntnodu$p8o$1@dont-email.me> |
Hello everyone,
I've just stumbled across this article:
memcpy (and friends) with NULL pointers
https://www.imperialviolet.org/2016/06/26/nonnull.html
which discusses an example of compiler optimization
in the face of undefined behavior. Namely:
#include <stdint.h>
#include <string.h>
int f(uint8_t *dest, uint8_t *src, size_t len) {
memcpy(dest, src, len);
return dest == NULL;
}
would remove the comparison, and unconditionally return 0.
This is similar to the bug found in Linux where someone
dereferenced a pointer, and only later tested for NULL,
and gcc removed the test.
Fun with NULL pointers, part 1
https://lwn.net/Articles/342330/
Regards.
[toc] | [next] | [standalone]
| From | Richard Heathfield <rjh@cpax.org.uk> |
|---|---|
| Date | 2016-10-13 11:55 +0100 |
| Message-ID | <ntnp5r$rob$1@dont-email.me> |
| In reply to | #94806 |
On 13/10/16 11:42, Noob wrote:
> Hello everyone,
>
> I've just stumbled across this article:
>
> memcpy (and friends) with NULL pointers
> https://www.imperialviolet.org/2016/06/26/nonnull.html
>
> which discusses an example of compiler optimization
> in the face of undefined behavior. Namely:
>
> #include <stdint.h>
> #include <string.h>
>
> int f(uint8_t *dest, uint8_t *src, size_t len) {
> memcpy(dest, src, len);
> return dest == NULL;
> }
>
> would remove the comparison, and unconditionally return 0.
The compiler's behaviour is both legal and reasonable. The test is in
the wrong place.
> This is similar to the bug found in Linux where someone
> dereferenced a pointer, and only later tested for NULL,
> and gcc removed the test.
Fair enough. If the dereference is legitimate, the test is pointless.
And if the dereference is illegitimate, all bets are off - the code is
broken. Either way, gcc is correct, and the bug is in the positioning of
the test, not the compiler's removal thereof.
--
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within
[toc] | [prev] | [next] | [standalone]
| From | Noob <root@127.0.0.1> |
|---|---|
| Date | 2016-10-13 13:09 +0200 |
| Message-ID | <ntnq0r$ukh$1@dont-email.me> |
| In reply to | #94807 |
I agree with what you wrote, but you're aware that you've
poured gasoline on the fire, right? :-)
On 13/10/2016 12:55, Richard Heathfield wrote:
> On 13/10/16 11:42, Noob wrote:
>> Hello everyone,
>>
>> I've just stumbled across this article:
>>
>> memcpy (and friends) with NULL pointers
>> https://www.imperialviolet.org/2016/06/26/nonnull.html
>>
>> which discusses an example of compiler optimization
>> in the face of undefined behavior. Namely:
>>
>> #include <stdint.h>
>> #include <string.h>
>>
>> int f(uint8_t *dest, uint8_t *src, size_t len) {
>> memcpy(dest, src, len);
>> return dest == NULL;
>> }
>>
>> would remove the comparison, and unconditionally return 0.
>
> The compiler's behaviour is both legal and reasonable.
> The test is in the wrong place.
Don't you find it somewhat inconsistent that free()
handles NULL, while memcpy doesn't?
Regards.
[toc] | [prev] | [next] | [standalone]
| From | Richard Heathfield <rjh@cpax.org.uk> |
|---|---|
| Date | 2016-10-13 12:22 +0100 |
| Message-ID | <ntnqpt$1if$1@dont-email.me> |
| In reply to | #94809 |
On 13/10/16 12:09, Noob wrote:
> I agree with what you wrote, but you're aware that you've
> poured gasoline on the fire, right? :-)
I wasn't aware there was a fire. Look, either you know for sure that the
pointer is not a null pointer, or you don't.
If you don't know, you'd better check *before* calling memcpy. And if
you do know, why bother to check afterwards?
It's a no-brainer. There is no legitimate controversy here as far as I
can see.
<snip>
> Don't you find it somewhat inconsistent that free()
> handles NULL, while memcpy doesn't?
No. The free() operation could be considered a bit of a lumbering bear.
When you call it, I'm kind of resigned to its maybe having to play a lot
of pointer games to get its data structures re-optimised after my
deallocation, so I don't mind if it does an extra check for NULL. But
memcpy() should be more like a humming-bird than a bear - so fast you
can't see it move. When I use memcpy() it's because I want the fastest,
leanest, meanest, most optimisedest, absolutely-no-fat copying operation
possible, and in return for that I am prepared to pay the laughably low
price of ensuring that I don't pass it a duff pointer (and that includes
pointers to overlapping areas).
If I want void *npsmemcpy(void*t,void*s,size_t
n){!t||!s||memcpy(t,s,n);return t;} I know how to write it.
--
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2016-10-13 12:22 -0700 |
| Message-ID | <95a7c522-f9ff-4cb1-8bf3-647e9d14fd95@googlegroups.com> |
| In reply to | #94810 |
On Thursday, October 13, 2016 at 6:23:03 AM UTC-5, Richard Heathfield wrote:
> No. The free() operation could be considered a bit of a lumbering bear.
> When you call it, I'm kind of resigned to its maybe having to play a lot
> of pointer games to get its data structures re-optimised after my
> deallocation, so I don't mind if it does an extra check for NULL. But
> memcpy() should be more like a humming-bird than a bear - so fast you
> can't see it move. When I use memcpy() it's because I want the fastest,
> leanest, meanest, most optimisedest, absolutely-no-fat copying operation
> possible, and in return for that I am prepared to pay the laughably low
> price of ensuring that I don't pass it a duff pointer (and that includes
> pointers to overlapping areas).
There are many APIs which accept a pointer and a size, and which specify
that it is legitimate to pass a null pointer with a size of zero. For
most implementations of memcpy, attempting to copy zero bytes will be a
no-op regardless of what pointers are passed in. If a platform's memcpy
is sophisticated enough to justify a subroutine call, the code:
if (size) memcpy(dest, src, size);
will end up checking size twice unless the implementation either:
1. has a special version of memcpy which presumes that the size will be at
least 1 and can use that after the check, or
2. knows that invoking memcpy with a size of zero will be an unconditional
no-op and it may thus omit the size check from the calling code.
The first scenario seems unlikely; in the second scenario, if the compiler
knows that invoking memcpy with a size of zero will be a no-op, there's no
reason it shouldn't regard it as a no-op in cases where the programmer
invokes it.
[toc] | [prev] | [next] | [standalone]
| From | "Rick C. Hodgin" <rick.c.hodgin@gmail.com> |
|---|---|
| Date | 2016-10-13 12:32 -0700 |
| Message-ID | <cec783db-b356-4b46-ae26-02d2cf13c770@googlegroups.com> |
| In reply to | #94841 |
On Thursday, October 13, 2016 at 3:22:17 PM UTC-4, supe...@casperkitty.com wrote:
> On Thursday, October 13, 2016 at 6:23:03 AM UTC-5, Richard Heathfield wrote:
> > No. The free() operation could be considered a bit of a lumbering bear.
> > When you call it, I'm kind of resigned to its maybe having to play a lot
> > of pointer games to get its data structures re-optimised after my
> > deallocation, so I don't mind if it does an extra check for NULL. But
> > memcpy() should be more like a humming-bird than a bear - so fast you
> > can't see it move. When I use memcpy() it's because I want the fastest,
> > leanest, meanest, most optimisedest, absolutely-no-fat copying operation
> > possible, and in return for that I am prepared to pay the laughably low
> > price of ensuring that I don't pass it a duff pointer (and that includes
> > pointers to overlapping areas).
>
> There are many APIs which accept a pointer and a size, and which specify
> that it is legitimate to pass a null pointer with a size of zero. For
> most implementations of memcpy, attempting to copy zero bytes will be a
> no-op regardless of what pointers are passed in. If a platform's memcpy
> is sophisticated enough to justify a subroutine call, the code:
>
> if (size) memcpy(dest, src, size);
>
> will end up checking size twice unless the implementation either:
>
> 1. has a special version of memcpy which presumes that the size will be at
> least 1 and can use that after the check, or
>
> 2. knows that invoking memcpy with a size of zero will be an unconditional
> no-op and it may thus omit the size check from the calling code.
>
> The first scenario seems unlikely; in the second scenario, if the compiler
> knows that invoking memcpy with a size of zero will be a no-op, there's no
> reason it shouldn't regard it as a no-op in cases where the programmer
> invokes it.
This is why I introduced type-ii and type-i function formats and i { }
blocks in CAlive. An example would be like this:
// Create a type-ii version
void* iimemcpy(void* p1, void* p2, size_t len)
{
// Code to include when imempcy() is used instead of iimemcpy()
i {
if (!p1 || !p2 || len == 0)
return(p1);
}
// Normal code here
}
In this case, the memcpy function can be called as iimemcpy() to
completely bypass the i { } block checks, or as imemcpy to include
their logic and respond appropriately.
I added this ability so that code which has already checked a pointer
value can call the iiVersion() and code that has not yet checked the
value can call the iVersion().
It's a speedup provided for these cases where it's possible the inputs
have already been examined and are known to be valid, therefore the
additional test is not needed.
Best regards,
Rick C. Hodgin
[toc] | [prev] | [next] | [standalone]
| From | "Rick C. Hodgin" <rick.c.hodgin@gmail.com> |
|---|---|
| Date | 2016-10-13 12:34 -0700 |
| Message-ID | <3fb6117f-9748-4d36-8062-050c44975d4e@googlegroups.com> |
| In reply to | #94843 |
On Thursday, October 13, 2016 at 3:32:45 PM UTC-4, Rick C. Hodgin wrote:
> On Thursday, October 13, 2016 at 3:22:17 PM UTC-4, supe...@casperkitty.com wrote:
> > On Thursday, October 13, 2016 at 6:23:03 AM UTC-5, Richard Heathfield wrote:
> > > No. The free() operation could be considered a bit of a lumbering bear.
> > > When you call it, I'm kind of resigned to its maybe having to play a lot
> > > of pointer games to get its data structures re-optimised after my
> > > deallocation, so I don't mind if it does an extra check for NULL. But
> > > memcpy() should be more like a humming-bird than a bear - so fast you
> > > can't see it move. When I use memcpy() it's because I want the fastest,
> > > leanest, meanest, most optimisedest, absolutely-no-fat copying operation
> > > possible, and in return for that I am prepared to pay the laughably low
> > > price of ensuring that I don't pass it a duff pointer (and that includes
> > > pointers to overlapping areas).
> >
> > There are many APIs which accept a pointer and a size, and which specify
> > that it is legitimate to pass a null pointer with a size of zero. For
> > most implementations of memcpy, attempting to copy zero bytes will be a
> > no-op regardless of what pointers are passed in. If a platform's memcpy
> > is sophisticated enough to justify a subroutine call, the code:
> >
> > if (size) memcpy(dest, src, size);
> >
> > will end up checking size twice unless the implementation either:
> >
> > 1. has a special version of memcpy which presumes that the size will be at
> > least 1 and can use that after the check, or
> >
> > 2. knows that invoking memcpy with a size of zero will be an unconditional
> > no-op and it may thus omit the size check from the calling code.
> >
> > The first scenario seems unlikely; in the second scenario, if the compiler
> > knows that invoking memcpy with a size of zero will be a no-op, there's no
> > reason it shouldn't regard it as a no-op in cases where the programmer
> > invokes it.
>
> This is why I introduced type-ii and type-i function formats and i { }
> blocks in CAlive. An example would be like this:
>
> // Create a type-ii version
> void* iimemcpy(void* p1, void* p2, size_t len)
> {
> // Code to include when imempcy() is used instead of iimemcpy()
> i {
> if (!p1 || !p2 || len == 0)
> return(p1);
> }
> // Normal code here
> }
>
> In this case, the memcpy function can be called as iimemcpy() to
> completely bypass the i { } block checks, or as imemcpy to include
> their logic and respond appropriately.
>
> I added this ability so that code which has already checked a pointer
> value can call the iiVersion() and code that has not yet checked the
> value can call the iVersion().
>
> It's a speedup provided for these cases where it's possible the inputs
> have already been examined and are known to be valid, therefore the
> additional test is not needed.
Here is the link:
https://groups.google.com/forum/#!topic/caliveprogramminglanguage/mqxBk0-lyqM
Best regards,
Rick C. Hodgin
[toc] | [prev] | [next] | [standalone]
| From | Joe Pfeiffer <pfeiffer@cs.nmsu.edu> |
|---|---|
| Date | 2016-10-13 08:24 -0600 |
| Message-ID | <1bh98ggwd0.fsf@pfeifferfamily.net> |
| In reply to | #94807 |
Richard Heathfield <rjh@cpax.org.uk> writes:
> On 13/10/16 11:42, Noob wrote:
>> Hello everyone,
>>
>> I've just stumbled across this article:
>>
>> memcpy (and friends) with NULL pointers
>> https://www.imperialviolet.org/2016/06/26/nonnull.html
>>
>> which discusses an example of compiler optimization
>> in the face of undefined behavior. Namely:
>>
>> #include <stdint.h>
>> #include <string.h>
>>
>> int f(uint8_t *dest, uint8_t *src, size_t len) {
>> memcpy(dest, src, len);
>> return dest == NULL;
>> }
>>
>> would remove the comparison, and unconditionally return 0.
>
> The compiler's behaviour is both legal and reasonable. The test is in
> the wrong place.
>
>> This is similar to the bug found in Linux where someone
>> dereferenced a pointer, and only later tested for NULL,
>> and gcc removed the test.
>
> Fair enough. If the dereference is legitimate, the test is
> pointless. And if the dereference is illegitimate, all bets are off -
> the code is broken. Either way, gcc is correct, and the bug is in the
> positioning of the test, not the compiler's removal thereof.
It really seems like both of these are things that ought to result in a
diagnostic. If the compiler can conclude a conditional that a
programmer presumably thought was needed in fact isn't, it would be nice
to inform the programmer of that fact....
[toc] | [prev] | [next] | [standalone]
| From | Richard Heathfield <rjh@cpax.org.uk> |
|---|---|
| Date | 2016-10-13 16:22 +0100 |
| Message-ID | <nto8qb$k48$2@dont-email.me> |
| In reply to | #94823 |
On 13/10/16 15:24, Joe Pfeiffer wrote: <snip> > It really seems like both of these are things that ought to result in a > diagnostic. If the compiler can conclude a conditional that a > programmer presumably thought was needed in fact isn't, it would be nice > to inform the programmer of that fact.... Oh, by all means, yes. But the compiler isn't actually /obliged/ to issue a diagnostic message in this situation. It's very much the kind of thing that you might reasonably hope for but which you cannot, strictly speaking, expect. -- Richard Heathfield Email: rjh at cpax dot org dot uk "Usenet is a strange place" - dmr 29 July 1999 Sig line 4 vacant - apply within
[toc] | [prev] | [next] | [standalone]
| From | Noob <root@127.0.0.1> |
|---|---|
| Date | 2016-10-13 17:49 +0200 |
| Message-ID | <ntoado$rdm$1@dont-email.me> |
| In reply to | #94823 |
On 13/10/2016 16:24, Joe Pfeiffer wrote:
> Richard Heathfield <rjh@cpax.org.uk> writes:
>
>> On 13/10/16 11:42, Noob wrote:
>>> Hello everyone,
>>>
>>> I've just stumbled across this article:
>>>
>>> memcpy (and friends) with NULL pointers
>>> https://www.imperialviolet.org/2016/06/26/nonnull.html
>>>
>>> which discusses an example of compiler optimization
>>> in the face of undefined behavior. Namely:
>>>
>>> #include <stdint.h>
>>> #include <string.h>
>>>
>>> int f(uint8_t *dest, uint8_t *src, size_t len) {
>>> memcpy(dest, src, len);
>>> return dest == NULL;
>>> }
>>>
>>> would remove the comparison, and unconditionally return 0.
>>
>> The compiler's behaviour is both legal and reasonable. The test is in
>> the wrong place.
>>
>>> This is similar to the bug found in Linux where someone
>>> dereferenced a pointer, and only later tested for NULL,
>>> and gcc removed the test.
>>
>> Fair enough. If the dereference is legitimate, the test is
>> pointless. And if the dereference is illegitimate, all bets are off -
>> the code is broken. Either way, gcc is correct, and the bug is in the
>> positioning of the test, not the compiler's removal thereof.
>
> It really seems like both of these are things that ought to result in a
> diagnostic. If the compiler can conclude a conditional that a
> programmer presumably thought was needed in fact isn't, it would be nice
> to inform the programmer of that fact....
Which reminds me of the thread David started in gcc-help.
https://www.spinics.net/lists/gcchelp/thrd2.html#44485
Regards.
[toc] | [prev] | [next] | [standalone]
| From | Joe Pfeiffer <pfeiffer@cs.nmsu.edu> |
|---|---|
| Date | 2016-10-13 12:02 -0600 |
| Message-ID | <1b8ttsgma7.fsf@pfeifferfamily.net> |
| In reply to | #94829 |
Noob <root@127.0.0.1> writes:
> On 13/10/2016 16:24, Joe Pfeiffer wrote:
>
>> Richard Heathfield <rjh@cpax.org.uk> writes:
>>
>>> On 13/10/16 11:42, Noob wrote:
>>>> Hello everyone,
>>>>
>>>> I've just stumbled across this article:
>>>>
>>>> memcpy (and friends) with NULL pointers
>>>> https://www.imperialviolet.org/2016/06/26/nonnull.html
>>>>
>>>> which discusses an example of compiler optimization
>>>> in the face of undefined behavior. Namely:
>>>>
>>>> #include <stdint.h>
>>>> #include <string.h>
>>>>
>>>> int f(uint8_t *dest, uint8_t *src, size_t len) {
>>>> memcpy(dest, src, len);
>>>> return dest == NULL;
>>>> }
>>>>
>>>> would remove the comparison, and unconditionally return 0.
>>>
>>> The compiler's behaviour is both legal and reasonable. The test is in
>>> the wrong place.
>>>
>>>> This is similar to the bug found in Linux where someone
>>>> dereferenced a pointer, and only later tested for NULL,
>>>> and gcc removed the test.
>>>
>>> Fair enough. If the dereference is legitimate, the test is
>>> pointless. And if the dereference is illegitimate, all bets are off -
>>> the code is broken. Either way, gcc is correct, and the bug is in the
>>> positioning of the test, not the compiler's removal thereof.
>>
>> It really seems like both of these are things that ought to result in a
>> diagnostic. If the compiler can conclude a conditional that a
>> programmer presumably thought was needed in fact isn't, it would be nice
>> to inform the programmer of that fact....
>
> Which reminds me of the thread David started in gcc-help.
> https://www.spinics.net/lists/gcchelp/thrd2.html#44485
I hadn't seen the thread, though I was aware of the controversy. After
reading a bunch (though not all) of the thread, I agree with David Brown
completely (and feel Andrew Haley is possibly too close to the problem
to see it).
[toc] | [prev] | [next] | [standalone]
| From | Lőrinczy Zsigmond <nospam@for.me> |
|---|---|
| Date | 2016-10-15 20:56 +0200 |
| Message-ID | <nttu4o$1fuc$1@gioia.aioe.org> |
| In reply to | #94806 |
Nice. A broken standard and a broken optimizer join forces to make programmers' life miserable... Standard should mandate that if len==0, memcpy has to return without checking any of the pointers, also compiler should do what it was told to, not something else it thinks is 'optimal'.
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2016-10-15 12:52 -0700 |
| Message-ID | <fca1f332-82be-4487-91dc-d39588d52b95@googlegroups.com> |
| In reply to | #94869 |
On Saturday, October 15, 2016 at 1:56:35 PM UTC-5, Lőrinczy Zsigmond wrote: > Standard should mandate that if len==0, > memcpy has to return without checking > any of the pointers, > also compiler should do what it was told to, > not something else it thinks is 'optimal'. That would have been helpful, but I think the authors of the Standard didn't think it was necessary to describe every possible case where there was one sensible behavior which was clear, obvious, and useful, and no imaginable purpose for any other. There are a lot of places where the Standard should have been more specific (e.g. having a version of memcpy which is explicitly documented as reading earlier locations before writing later ones, and probably also one documented as the reverse, since in many cases code will know whether it's copying things up or down) but non-contrived situations where requiring memcpy(anything, anything, 0) to be a no-op would add any cost *whatsoever* are very rare; by contrast, in many APIs, requiring that programmers avoid memcpy(buff, NULL, 0) will necessitate adding additional special-case logic in code that handles certain APIs, and in many cases that logic can't be optimized away.
[toc] | [prev] | [next] | [standalone]
| From | "James R. Kuyper" <jameskuyper@verizon.net> |
|---|---|
| Date | 2016-10-15 15:55 -0400 |
| Message-ID | <5d3b068a-c63c-7dca-ed3a-bdbc94250c36@verizon.net> |
| In reply to | #94869 |
On 10/15/2016 02:56 PM, Lőrinczy Zsigmond wrote: > Nice. A broken standard and a broken optimizer join forces to make > programmers' life miserable... > > Standard should mandate that if len==0, > memcpy has to return without checking > any of the pointers, I can agree with that. Null pointers are given by the standard as generic examples of invalid arguments, but whether or not they actually are invalid arguments depends upon the function being called. The committee currently interprets the C standard as giving defined behavior to calls of standard library functions with null pointer arguments only if the description specifically says something about the behavior when the value is null. That is true for only a couple of dozen functions. Note: f() does nothing to check whether or not len==0 before calling memcpy(). > also compiler should do what it was told to, > not something else it thinks is 'optimal'. If f() is called with len>=0, that's already the case. According to the current standard, that code told the compiler "Do whatever you want to do", so the compiler was, in fact, doing what it was told to do. It would be literally impossible for it to not do what it was told to do.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2016-10-15 13:41 -0700 |
| Message-ID | <lnvawtgxb0.fsf@kst-u.example.com> |
| In reply to | #94869 |
Lőrinczy Zsigmond <nospam@for.me> writes:
> Nice. A broken standard and a broken optimizer join forces to make
> programmers' life miserable...
>
> Standard should mandate that if len==0,
> memcpy has to return without checking
> any of the pointers,
> also compiler should do what it was told to,
> not something else it thinks is 'optimal'.
As a programmer, how much of a burden is it to avoid calling memcpy()
with a null pointer?
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | Lőrinczy Zsigmond <nospam@for.me> |
|---|---|
| Date | 2016-10-16 11:17 +0200 |
| Message-ID | <ntvgk3$1efo$1@gioia.aioe.org> |
| In reply to | #94876 |
> As a programmer, how much of a burden is it to avoid calling memcpy() > with a null pointer? It would add a redundant 'if' to the code, increasing complexity - memcpy (to, from, len) + if (len) memcpy (to, from, len)
[toc] | [prev] | [next] | [standalone]
| From | Richard Heathfield <rjh@cpax.org.uk> |
|---|---|
| Date | 2016-10-16 10:26 +0100 |
| Message-ID | <ntvh2p$vrf$1@dont-email.me> |
| In reply to | #94907 |
On 16/10/16 10:17, Lőrinczy Zsigmond wrote: > >> As a programmer, how much of a burden is it to avoid calling memcpy() >> with a null pointer? > > It would add a redundant 'if' to the code, increasing complexity > > - memcpy (to, from, len) > + if (len) memcpy (to, from, len) Most times, I know whether I have anything to copy. I would rather add the test myself on the vanishingly rare occasions when it's necessary than to force memcpy to invoke the test itself on every single call. -- Richard Heathfield Email: rjh at cpax dot org dot uk "Usenet is a strange place" - dmr 29 July 1999 Sig line 4 vacant - apply within
[toc] | [prev] | [next] | [standalone]
| From | raltbos@xs4all.nl (Richard Bos) |
|---|---|
| Date | 2016-10-16 09:55 +0000 |
| Message-ID | <58034cbc.2767375@news.xs4all.nl> |
| In reply to | #94907 |
=?UTF-8?Q?L=c5=91rinczy_Zsigmond?= <nospam@for.me> wrote:
>
> > As a programmer, how much of a burden is it to avoid calling memcpy()
> > with a null pointer?
>
> It would add a redundant 'if' to the code, increasing complexity
>
> - memcpy (to, from, len)
> + if (len) memcpy (to, from, len)
Nope. Testing for null pointers should be done as early and as high up
as possible, _not_ in system code nor every single time you call a
system function. That way, you avoid a whole slew of if's with a single
one, rather than risk missing one.
Demanding that the check be done in system code also means that _all_
calls to that system function suffer the penalty, even those in code
that's written properly, with the big picture in mind.
In other words, don't write this:
string=get_string(parameters);
if(string) do_something_with_string(string);
do_something_else();
if (string) len=strlen(string);
if (string) memcpy(newstring, string, len);
do_yet_another_thing();
if (string) printf("This is the string: %s, string);
or this:
string=get_string(parameters);
do_something_with_string(string); // Which has an if(str) inside
do_something_else();
len=strlen(string); // Oops... strlen doesn't have an if(str) inside!
memcpy(newstring, string, len); // Which you demand does if(str)
do_yet_another_thing();
printf("This is the string: %s, string); // Which, again...
but do this:
string=get_string(parameters);
if(string) {
do_something_with_string(string);
do_something_else();
len=strlen(string);
memcpy(newstring, string, len);
do_yet_another_thing();
printf("This is the string: %s, string);
} else {
/* You can even add error code to this case, which is harder in
the two previous ones unless you go for an immediate abort. */
}
Clean, clear and efficient.
Richard
[toc] | [prev] | [next] | [standalone]
| From | Jerry Stuckle <jstucklex@attglobal.net> |
|---|---|
| Date | 2016-10-16 08:44 -0400 |
| Message-ID | <ntvsn5$51p$1@jstuckle.eternal-september.org> |
| In reply to | #94912 |
On 10/16/2016 5:55 AM, Richard Bos wrote: > =?UTF-8?Q?L=c5=91rinczy_Zsigmond?= <nospam@for.me> wrote: > >> >>> As a programmer, how much of a burden is it to avoid calling memcpy() >>> with a null pointer? >> >> It would add a redundant 'if' to the code, increasing complexity >> >> - memcpy (to, from, len) >> + if (len) memcpy (to, from, len) > > Nope. Testing for null pointers should be done as early and as high up > as possible, _not_ in system code nor every single time you call a > system function. That way, you avoid a whole slew of if's with a single > one, rather than risk missing one. > Demanding that the check be done in system code also means that _all_ > calls to that system function suffer the penalty, even those in code > that's written properly, with the big picture in mind. > In other words, don't write this: > Which can cause a problem with embedded and kernel programming, where location 0 is a valid address. In many systems (including Intel processors), for instance, this is the beginning of the interrupt vectors, which must be set during initialization. It is very possible to set multiple vectors with one call to memcpy. Forcing library functions to test for a null pointer would preclude using them for these functions. -- ================== Remove the "x" from my email address Jerry Stuckle jstucklex@attglobal.net ==================
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2016-10-17 10:06 +0200 |
| Message-ID | <nu20q4$8u6$1@dont-email.me> |
| In reply to | #94925 |
On 16/10/16 14:44, Jerry Stuckle wrote: > On 10/16/2016 5:55 AM, Richard Bos wrote: >> =?UTF-8?Q?L=c5=91rinczy_Zsigmond?= <nospam@for.me> wrote: >> >>> >>>> As a programmer, how much of a burden is it to avoid calling memcpy() >>>> with a null pointer? >>> >>> It would add a redundant 'if' to the code, increasing complexity >>> >>> - memcpy (to, from, len) >>> + if (len) memcpy (to, from, len) >> >> Nope. Testing for null pointers should be done as early and as high up >> as possible, _not_ in system code nor every single time you call a >> system function. That way, you avoid a whole slew of if's with a single >> one, rather than risk missing one. >> Demanding that the check be done in system code also means that _all_ >> calls to that system function suffer the penalty, even those in code >> that's written properly, with the big picture in mind. >> In other words, don't write this: >> > > Which can cause a problem with embedded and kernel programming, where > location 0 is a valid address. In many systems (including Intel > processors), for instance, this is the beginning of the interrupt > vectors, which must be set during initialization. It is very possible > to set multiple vectors with one call to memcpy. > In practice, while location 0 is usually a valid address in embedded systems, it is typically a rather special address. A common case is for the reset vector or initial stack pointer. Sometimes (especially on small microcontrollers) it can be part of the hardware register map. You would rarely want to access such locations through a pointer, and you certainly don't want to do so via memcpy or similar functions. Quite simply, it is not a problem. > Forcing library functions to test for a null pointer would preclude > using them for these functions. I interpreted Richard's post to mean that any tests for null pointers (or other special cases) should be handled in application code /before/ calling library functions - thus the library functions don't need to check for null pointers, and could perhaps even allow their usage. The only sensible attitude is to avoid calling memcpy and similar functions with null pointers. The standard says memcpy has undefined behaviour for null pointers, to give the compiler and library implementers full freedom to choose the optimal code. So you do any required checks before calling them.
[toc] | [prev] | [next] | [standalone]
Page 1 of 5 [1] 2 3 4 5 Next page →
Back to top | Article view | comp.lang.c
csiph-web