From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTP id 01302385782A for ; Tue, 13 Apr 2021 00:26:03 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 01302385782A Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-328-ZKc8QA0PNcGjH7Ir1Z_apQ-1; Mon, 12 Apr 2021 20:26:02 -0400 X-MC-Unique: ZKc8QA0PNcGjH7Ir1Z_apQ-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 4CB186415B; Tue, 13 Apr 2021 00:26:01 +0000 (UTC) Received: from rhel8.vm.delorie.com (ovpn-112-40.rdu2.redhat.com [10.10.112.40]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 112BB1F07F; Tue, 13 Apr 2021 00:26:00 +0000 (UTC) Received: from rhel8.vm.redhat.com (localhost [127.0.0.1]) by rhel8.vm.delorie.com (8.15.2/8.15.2) with ESMTP id 13D0Px6g378209; Mon, 12 Apr 2021 20:25:59 -0400 From: DJ Delorie To: Paul Eggert Cc: libc-alpha@sourceware.org Subject: Re: Improve documentation for malloc etc. (BZ#27720) In-Reply-To: (message from Paul Eggert on Sun, 11 Apr 2021 19:18:18 -0700) Date: Mon, 12 Apr 2021 20:25:59 -0400 Message-ID: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain X-Spam-Status: No, score=-12.3 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 13 Apr 2021 00:26:06 -0000 Reviewing just the malloc bits. One bug, OK if that's fixed. Reviewed-by: DJ Delorie Paul Eggert writes: > diff --git a/manual/memory.texi b/manual/memory.texi > - struct foobar *ptr > - = (struct foobar *) malloc (sizeof (struct foobar)); > + struct foobar *ptr = malloc (sizeof *ptr); Ok. > -This malloc may allocate memory in two different ways depending on their size > +This @code{malloc} may allocate memory > +in two different ways depending on their size Ok. > -bytes long, or a null pointer if the block could not be allocated. > +bytes long, or a null pointer (setting @code{errno}) > +if the block could not be allocated. Ok. > -Normally you would cast the value as a pointer to the kind of object > +Normally you would convert the value to a pointer to the kind of object Ok. > -struct foo *ptr; > -@dots{} > -ptr = (struct foo *) malloc (sizeof (struct foo)); > +struct foo *ptr = malloc (sizeof *foo); Should be sizeof *ptr > -@code{void *} to another type of pointer when necessary. But the cast > -is necessary in contexts other than assignment operators or if you might > -want your code to run in traditional C. > +@code{void *} to another type of pointer when necessary. However, a cast > +is necessary if the type is needed but not specified by context. Ok. > @smallexample > -char *ptr; > -@dots{} > -ptr = (char *) malloc (length + 1); > +char *ptr = malloc (length + 1); > @end smallexample Ok. > nonzero. This function is conventionally called @code{xmalloc}. Here > it is: > +@cindex @code{xmalloc} function Ok. > char * > savestring (const char *ptr, size_t len) > @{ > - char *value = (char *) xmalloc (len + 1); > + char *value = xmalloc (len + 1); > value[len] = '\0'; > - return (char *) memcpy (value, ptr, len); > + return memcpy (value, ptr, len); > @} Ok. > +@strong{Portability Notes:} > + > +@itemize @bullet > +@item > +In @theglibc{}, a successful @code{malloc (0)} > +returns a non-null pointer to a newly allocated size-zero block; > +other implementations may return @code{NULL} instead. > +POSIX and the ISO C standard allow both behaviors. > + > +@item > +In @theglibc{}, a failed @code{malloc} call sets @code{errno}, > +but ISO C does not require this and non-POSIX implementations > +need not set @code{errno} when failing. > + > +@item > +In @theglibc{}, @code{malloc} always fails when @var{size} exceeds > +@code{PTRDIFF_MAX}, to avoid problems with programs that subtract > +pointers or use signed indexes. Other implementations may succeed in > +this case, leading to undefined behavior later. > +@end itemize > + Ok. > @@ -817,10 +835,12 @@ block. If the block needs to be moved, @code{realloc} copies the old > contents. > > If you pass a null pointer for @var{ptr}, @code{realloc} behaves just > -like @samp{malloc (@var{newsize})}. This can be convenient, but beware > -that older implementations (before @w{ISO C}) may not support this > -behavior, and will probably crash when @code{realloc} is passed a null > -pointer. > +like @samp{malloc (@var{newsize})}. > +Otherwise, if @var{newsize} is zero > +@code{realloc} frees the block and returns @code{NULL}. > +Otherwise, if @code{realloc} cannot reallocate the requested size > +it returns @code{NULL} and sets @code{errno}; the original block > +is left undisturbed. > @end deftypefun Ok. > @@ -850,19 +870,27 @@ relocated. > In most cases it makes no difference what happens to the original block > when @code{realloc} fails, because the application program cannot continue > when it is out of memory, and the only thing to do is to give a fatal error > -message. Often it is convenient to write and use a subroutine, > -conventionally called @code{xrealloc}, that takes care of the error message > +message. Often it is convenient to write and use subroutines, > +conventionally called @code{xrealloc} and @code{xreallocarray}, > +that take care of the error message > as @code{xmalloc} does for @code{malloc}: > +@cindex @code{xrealloc} and @code{xreallocarray} functions Ok. > @smallexample > void * > -xrealloc (void *ptr, size_t size) > +xreallocarray (void *ptr, size_t nmemb, size_t size) > @{ > - void *value = realloc (ptr, size); > + void *value = reallocarray (ptr, nmemb, size); > if (value == 0) > fatal ("Virtual memory exhausted"); > return value; > @} > + > +void * > +xrealloc (void *ptr, size_t size) > +@{ > + return xreallocarray (ptr, 1, size); > +@} > @end smallexample Ok. > @@ -873,9 +901,28 @@ space when only a little is needed. > In several allocation implementations, making a block smaller sometimes > necessitates copying it, so it can fail if no other space is available. > > -If the new size you specify is the same as the old size, @code{realloc} and > +@strong{Portability Notes:} > + > +@itemize @bullet > +@item > +Portable programs should not attempt to reallocate blocks to be size zero. > +On other implementations if @var{ptr} is non-null, @code{realloc (ptr, 0)} > +might free the block and return a non-null pointer to a size-zero > +object, or it might fail and return @code{NULL} without freeing the block. > +The ISO C17 standard allows these variations. > + > +@item > +In @theglibc{}, reallocation fails if the resulting block > +would exceed @code{PTRDIFF_MAX} in size, to avoid problems with programs > +that subtract pointers or use signed indexes. Other implementations may > +succeed, leading to undefined behavior later. > + > +@item > +In @theglibc{}, if the new size is the same as the old, @code{realloc} and > @code{reallocarray} are guaranteed to change nothing and return the same > -address that you gave. > +address that you gave. However, POSIX and ISO C allow the functions > +to relocate the object or fail in this situation. > +@end itemize Ok. > @@ -916,18 +963,20 @@ You could define @code{calloc} as follows: > void * > calloc (size_t count, size_t eltsize) > @{ > - size_t size = count * eltsize; > - void *value = malloc (size); > + void *value = reallocarray (0, count, eltsize); > if (value != 0) > - memset (value, 0, size); > + memset (value, 0, count * eltsize); > return value; > @} > @end smallexample Ok. > But in general, it is not guaranteed that @code{calloc} calls > -@code{malloc} internally. Therefore, if an application provides its own > -@code{malloc}/@code{realloc}/@code{free} outside the C library, it > -should always define @code{calloc}, too. > +@code{reallocarray} and @code{memset} internally. For example, if the > +@code{calloc} implementation knows for other reasons that the new > +memory block is zero, it need not zero out the block again with > +@code{memset}. Also, if an application provides its own > +@code{reallocarray} outside the C library, @code{calloc} might not use > +that redefinition. @xref{Replacing malloc}. Ok. > -An issue to look out for is the time at which the malloc hook functions > -can be safely installed. If the hook functions call the malloc-related > -functions recursively, it is necessary that malloc has already properly > +An issue to look out for is the time at which the hook functions > +can be safely installed. If the hook functions call the @code{malloc}-related > +functions recursively, it is necessary that @code{malloc} has already properly > initialized itself at the time when @code{__malloc_hook} etc. is > assigned to. On the other hand, if the hook functions provide a > -complete malloc implementation of their own, it is vital that the hooks > +complete @code{malloc} implementation of their own, it is vital that the hooks > are assigned to @emph{before} the very first @code{malloc} call has > completed, because otherwise a chunk obtained from the ordinary, > -un-hooked malloc may later be handed to @code{__free_hook}, for example. > +un-hooked @code{malloc} may later be handed to @code{__free_hook}, for example. Ok. > - char *name = (char *) malloc (strlen (str1) + strlen (str2) + 1); > + char *name = malloc (strlen (str1) + strlen (str2) + 1); Ok. > diff --git a/manual/tunables.texi b/manual/tunables.texi > -example enables malloc checking and sets the malloc trim threshold to 128 > +example enables @code{malloc} checking and sets the @code{malloc} > +trim threshold to 128 Ok. > -efficient) memory allocator for the malloc family of functions that is > +efficient) memory allocator for the @code{malloc} family of functions that is Ok. > -allocated by calloc) and freed. This can be used to debug the use of > +allocated by @code{calloc}) and freed. This can be used to debug the use of Ok. > @deftp Tunable glibc.malloc.mxfast > -One of the optimizations malloc uses is to maintain a series of ``fast > +One of the optimizations @code{malloc} uses is to maintain a series of ``fast Ok. > -includes malloc's internal overhead, which is normally the size of one > +includes @code{malloc}'s internal overhead, which is normally the size of one Ok. > -Bit 0 (the least significant bit) causes the malloc subsystem to allocate > +Bit 0 (the least significant bit) causes the @code{malloc} > +subsystem to allocate Ok. > diff --git a/manual/users.texi b/manual/users.texi > @@ -578,7 +578,7 @@ supplementary_groups (char *user) > > if (getgrouplist (pw->pw_name, pw->pw_gid, groups, &ngroups) < 0) > @{ > - groups = xrealloc (ngroups * sizeof (gid_t)); > + groups = xreallocarray (ngroups, sizeof *groups); > getgrouplist (pw->pw_name, pw->pw_gid, groups, &ngroups); > @} > return groups; Ok.