Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #94806 > unrolled thread

UB of memcpy(NULL, NULL, 0)

Started byNoob <root@127.0.0.1>
First post2016-10-13 12:42 +0200
Last post2016-10-22 16:33 -0700
Articles 20 on this page of 100 — 20 participants

Back to article view | Back to comp.lang.c


Contents

  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 →


#94806 — UB of memcpy(NULL, NULL, 0)

FromNoob <root@127.0.0.1>
Date2016-10-13 12:42 +0200
SubjectUB 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]


#94807

FromRichard Heathfield <rjh@cpax.org.uk>
Date2016-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]


#94809

FromNoob <root@127.0.0.1>
Date2016-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]


#94810

FromRichard Heathfield <rjh@cpax.org.uk>
Date2016-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]


#94841

Fromsupercat@casperkitty.com
Date2016-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]


#94843

From"Rick C. Hodgin" <rick.c.hodgin@gmail.com>
Date2016-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]


#94844

From"Rick C. Hodgin" <rick.c.hodgin@gmail.com>
Date2016-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]


#94823

FromJoe Pfeiffer <pfeiffer@cs.nmsu.edu>
Date2016-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]


#94824

FromRichard Heathfield <rjh@cpax.org.uk>
Date2016-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]


#94829

FromNoob <root@127.0.0.1>
Date2016-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]


#94835

FromJoe Pfeiffer <pfeiffer@cs.nmsu.edu>
Date2016-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]


#94869

FromLőrinczy Zsigmond <nospam@for.me>
Date2016-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]


#94872

Fromsupercat@casperkitty.com
Date2016-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]


#94873

From"James R. Kuyper" <jameskuyper@verizon.net>
Date2016-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]


#94876

FromKeith Thompson <kst-u@mib.org>
Date2016-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]


#94907

FromLőrinczy Zsigmond <nospam@for.me>
Date2016-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]


#94908

FromRichard Heathfield <rjh@cpax.org.uk>
Date2016-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]


#94912

Fromraltbos@xs4all.nl (Richard Bos)
Date2016-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]


#94925

FromJerry Stuckle <jstucklex@attglobal.net>
Date2016-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]


#94959

FromDavid Brown <david.brown@hesbynett.no>
Date2016-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