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


Groups > comp.lang.c > #151159

Re: memcpy can't take null.

From Keith Thompson <Keith.S.Thompson+u@gmail.com>
Newsgroups comp.lang.c
Subject Re: memcpy can't take null.
Date 2020-04-06 14:30 -0700
Organization None to speak of
Message-ID <87y2r8mhei.fsf@nosuchdomain.example.com> (permalink)
References <6c3de07e-15c8-4cc0-a805-636a5976d086@googlegroups.com> <87a73ppmgj.fsf@nosuchdomain.example.com> <07c3ec1e-d2d5-41a3-bbc7-6e37b6464c01@googlegroups.com>

Show all headers | View raw


Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:
> On Monday, 6 April 2020 00:00:41 UTC+1, Keith Thompson  wrote:
>> Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:
>> > memcpy() cannot take null as a pointer parametrer, even if the size argument
>> > is zero.
>> >
>> > So what are the implications for passing empty buffers about? For example,
>> > how would people write
>> >
>> > /* struct employee has no embedded pointers */
>> >
>> > Employee *duplicateEmployees(Employee *employees, int Nemployees)
>> 
>> C doesn't directly support empty arrays, but since arrays are usually
>> manipulated via pointers to the initial element, it's easy enough
>> to treat a pointer as pointing to an empty array.
>> 
>> A null pointer doesn't point to an empty array.  It doesn't point
>> to *anything*.  Similarly, a null pointer doesn't point to an empty
>> string (there have been problems in the past with code that assumed
>> it did, and that happened to "work" on some systems).
>> 
>> Just keep that consistently in mind, and write your code in
>> whatever way is necessary to maintain that.  This might require
>> a little special case code for handling the result of malloc(0).
>> So write that code.
>> 
>> Employee *duplicateEmployees(Employee *employees, size_t Nemployees) {
>>     const size_t requestedCount = Nemployees + (Nemployees == 0);
>>     Employee *const new = malloc(requestedCount * sizeof *new);
>>     if (new != NULL) {
>>         memcpy(new, employees, Nemployees * sizeof *new);
>>     }
>>     return new;
>> }
>> 
>> An alternative would be to treat a null pointer as a pointer to an
>> empty array, but then you'd probably need more special case code on
>> top of that to keep things consistent (to avoid passing null pointers
>> to memcpy, for example).  By *not* treating a null pointer as a
>> pointer to an empty array, you can (probably) isolate the special
>> case code to allocation functions.  You'd also lose the ability to
>> use a null pointer as a special value that doesn't point to anything.
>> 
>> 
> I think this is the best answer.
>
> The standard library doesn't accept NULL as a valid pointer to the
> empty array, so it's reasonable to say that user-defined functions
> don't accept it either. That means that if you are passed a non-
> null pointer (presumably valid) with a size of zero, you should pass
> back a valid pointer. Otherwise caller suddenly finds NULLs infesting
> what he thought were valid empty arrays.
>
> if you are passed NULL and non-zero for the size, it is clearly
> an error, and it's best to pass it onto memcpy in the hope that
> memcpy will crash out. Since we don't know what we are running on,
> the implementation has a better idea how to crash the program
> than we do. You shouldn't suppress the error and pass back NULL -
> that's making it harder for caller to find where the bug lies.
>
> But if you are passed NULL and zero for the size, should you still
> pass it on to memcpy() ?

You should decide *and document* what argument values are valid, and
what values are invalid.  If a function receives invalid values, either
it should behave in some documented manner, or the documentation should
say that it's the caller's responsibility to pass only valid arguments
(otherwise the behavior is undefined).

For some functions, a null pointer might be valid, indicating that there
is no array (distinct from an empty array).  For others, a null pointer
might be invalid.  Decide and document.

You might consider wrapping the address and count in a structure.

-- 
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for Philips Healthcare
void Void(void) { Void(); } /* The recursive call of the void */

Back to comp.lang.c | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread


Thread

memcpy can't take null. Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2020-04-05 06:47 -0700
  Re: memcpy can't take null. Öö Tiib <ootiib@hot.ee> - 2020-04-05 07:30 -0700
    Re: memcpy can't take null. Richard Damon <Richard@Damon-Family.org> - 2020-04-05 14:39 -0400
      Re: memcpy can't take null. Philipp Klaus Krause <pkk@spth.de> - 2020-04-06 18:46 +0200
        Re: memcpy can't take null. Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2020-04-06 12:45 -0700
          Re: memcpy can't take null. Philipp Klaus Krause <pkk@spth.de> - 2020-04-07 07:28 +0200
  Re: memcpy can't take null. Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2020-04-05 16:00 -0700
    Re: memcpy can't take null. Joe Pfeiffer <pfeiffer@cs.nmsu.edu> - 2020-04-05 18:29 -0600
      Re: memcpy can't take null. scott@slp53.sl.home (Scott Lurndal) - 2020-04-06 18:08 +0000
        Re: memcpy can't take null. Joe Pfeiffer <pfeiffer@cs.nmsu.edu> - 2020-04-06 15:44 -0600
    Re: memcpy can't take null. Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2020-04-06 13:54 -0700
      Re: memcpy can't take null. Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2020-04-06 14:30 -0700
  Re: memcpy can't take null. Ben Bacarisse <ben.usenet@bsb.me.uk> - 2020-04-06 01:20 +0100
  Re: memcpy can't take null. Siri Cruise <chine.bleu@yahoo.com> - 2020-04-05 19:09 -0700
  Re: memcpy can't take null. Guillaume <message@bottle.org> - 2020-04-07 16:50 +0200
    Re: memcpy can't take null. Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2020-04-07 09:19 -0700
    Re: memcpy can't take null. Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2020-04-07 09:21 -0700
      Re: memcpy can't take null. Guillaume <message@bottle.org> - 2020-04-08 01:41 +0200
        Re: memcpy can't take null. scott@slp53.sl.home (Scott Lurndal) - 2020-04-08 00:30 +0000
          Re: memcpy can't take null. Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2020-04-08 02:06 -0700
            Re: memcpy can't take null. Richard Damon <Richard@Damon-Family.org> - 2020-04-08 09:17 -0400
              Re: memcpy can't take null. Tim Rentsch <tr.17687@z991.linuxsc.com> - 2020-04-09 07:16 -0700
            Re: memcpy can't take null. Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2020-04-08 13:33 -0700
              Re: memcpy can't take null. Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2020-04-09 09:05 -0700
                Re: memcpy can't take null. Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2020-04-09 13:28 -0700
                Re: memcpy can't take null. richard@cogsci.ed.ac.uk (Richard Tobin) - 2020-04-09 23:41 +0000
          Re: memcpy can't take null. Guillaume <message@bottle.org> - 2020-04-08 16:17 +0200
    Re: memcpy can't take null. Ike Naar <ike@sdf.lonestar.org> - 2020-04-07 22:01 +0000
      Re: memcpy can't take null. Guillaume <message@bottle.org> - 2020-04-08 01:32 +0200

csiph-web