strerror_r
strerror_r
is a function
specified by POSIX
which is not only a thread-safe way to get a (possibly locale-dependent) error message string,
but which also offers the caller control of the allocation of the string which may lend itself
useful if the string is to be modified. Its prototype given by POSIX is
#include <string.h>
int strerror_r(int, char *,
size_t)
where the first parameter specifies the error number we want a string for, and
the other two parameters are the buffer to store it in as well as its size. Like
the POSIX threads functions, strerror_r
returns its error number
as opposed to setting errno
. ERANGE
indicates the buffer
was too small to store the contents of the entire string, and the contents of the
buffer are undefined, although the majority of implementations store a
truncated error string in the buffer and usually terminate it with a null byte as well.
strerror_r
The POSIX Issue 8 drafts incorporate the following addition
to the Application Usage section:
Applications should use
strerror_l()
rather than strerror()
or strerror_r()
to avoid thread safety and possible alternative (non-conforming)
versions of these functions in some implementations.
What they're alluding to is the fact that the GNU C Library provides their own variant of
strerror_r
in addition to the POSIX version. Which version one gets depends on
what feature test macros are defined. If one defines _POSIX_C_SOURCE
or
_XOPEN_SOURCE
, as one always should in a program destined to be portable and
to leverage the standard, then one gets the proper POSIX definition. It would be a
shame if this clash with GNU would reduce the usage of an otherwise good interface.
Another criticism is, how does one figure out what size buffer is big enough? One could
dynamically allocate a buffer and just keep realloc
ing until strerror_r
no longer fails, but this is sloppy. Fortunately, POSIX also defines the constant NL_TEXTMAX
in limits.h
, which is the length of the longest possible message string (which
includes error message strings from strerror
). It is enough to declare a buffer
with size NL_TEXTMAX
, and strerror_r
should not fail with ERANGE
.
This means that one can avoid the need for dynamic allocation altogether if this is desirable, although one
should check that a buffer this large can be automatically allocated safely.