Date: Mon, 28 May 2018 18:37:54 +1000 (EST) From: Bruce Evans <brde@optusnet.com.au> To: Marcelo Araujo <araujo@freebsd.org> Cc: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: Re: svn commit: r334275 - head/lib/libc/string Message-ID: <20180528155019.W2534@besplex.bde.org> In-Reply-To: <201805280501.w4S51hbH046599@repo.freebsd.org> References: <201805280501.w4S51hbH046599@repo.freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
On Mon, 28 May 2018, Marcelo Araujo wrote: > Log: > Update strsep(3) EXAMPLE section regards the usage of assert(3). > > As many people has pointed out, using assert(3) shall be not the best approach > to verify if strdup(3) has allocated memory to string. > > Reviewed by: imp > Modified: head/lib/libc/string/strsep.3 > ============================================================================== > --- head/lib/libc/string/strsep.3 Mon May 28 04:38:10 2018 (r334274) > +++ head/lib/libc/string/strsep.3 Mon May 28 05:01:42 2018 (r334275) > @@ -31,7 +31,7 @@ > .\" @(#)strsep.3 8.1 (Berkeley) 6/9/93 > .\" $FreeBSD$ > .\" > -.Dd December 5, 2008 > +.Dd May 28, 2018 > .Dt STRSEP 3 > .Os > .Sh NAME > @@ -86,12 +86,12 @@ to parse a string, and prints each token in separate l > char *token, *string, *tofree; > > tofree = string = strdup("abc,def,ghi"); > -assert(string != NULL); > +if (string != NULL) > + while ((token = strsep(&string, ",")) != NULL) > + printf("%s\en", token); > > -while ((token = strsep(&string, ",")) != NULL) > - printf("%s\en", token); > - > free(tofree); > +free(string); > .Ed > .Pp > The following uses This is even worse than before. Errors are now mishandled in all cases by silently ignoring them. On most arches, null pointers are handled better than with assert() by the default error handling of sending a SIGSEGV to the process; this normally terminates it and dumps core. All assert() does is give a message that is only slightly better than nothing when it work, and then sends a SIGABRT to the process after breaking restartability by doing this in the non-returning functions abort(). That is without NDEBUG. NDEBUG gives the better default error handling. Note that assert() can't be used in signal handlers since it is required to print to stderr due to C not having any output methods except stdio. Even printing to stderr is fragile, especially after malloc() failures, since stderr might be buffered and delayed allocation of its buffer might fail. The FreeBSD implementation falls back to unbuffered then (or fails in setvbuf()), but the C standard doesn't require this. malloc() failures "can't happen" anyway, especially for strdup(). I used to test them using rlimits. IIRC, ulimit -d and ulimit -m used to work to restrict malloc() when malloc() used sbrk(). But now malloc() uses mmap() and limits don't work for it. Also, malloc() on at least amd64 now takes more than 2MB before doing anything (2MB for __je_extents_rtree and a mere few hundred KB for other parts of malloc()). malloc() might fail, but hundreds if not thousands of small strdup()s can probably be done in just the slop required to fit malloc()'s overhead. Bruce
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20180528155019.W2534>