Does free() set errno?

If buf is a malloc() allocated char buffer, does free(buf) set/reset errno?

Let's say I want to write the buffer to a file, and then free it, as I don't need it any more.

Let's say the error policy for the code is to return -1 on an error.

Is this a proper way to write out the buffer and error check without leaking memory?

fputs(buf, somefile);
free(buf);
if (errno) return -1;

Or do I need to consider free possibly setting errno, as in...

fputs(buf, somefile);
if (errno){ 
    free(buf);
    return -1;
}
free(buf);

or, horror of horrors,

do { 
  fputs(buf, somefile);
  int save_errno = errno;
  free(buf);
  errno = save_errno;
  if (errno) return -1;
} while(0);  

where the use of a block allows for a local save_errno to exist in various places should this need to be reused.

All of this would seem to depend on whether free() sets errno.

The linux man page for free() is also the man page for malloc(), etc. It mentions malloc() setting errno, but not free().

The GNU C Library manual page for freeing dynamic memory does not mention whether free() sets errno.

So I wrote a short program to force a write error so I could see if free() reset errno, and it does not. I'm wondering if I should rely upon this result and the fact that free() is so essential that "of course it doesn't set errno."

# See if free() resets errno on a bad write
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char **argv)
{
  char * buf = malloc(256);
  snprintf(buf,256,"%s\n", "Hello, World!");

  FILE *badfile;

  badfile = fopen("/dev/null","r");

  fputs(buf, badfile);
  free(buf);
  printf("%d\n", errno);
  printf("%s\n", strerror(errno));
}

Solution 1:

POSIX doesn't define free to set errno (although POSIX doesn't currently forbid it, so an implementation might do so - refer to @ArjunShankar's answer for more details). But that's not really relevant to your concern.

The way you're checking for errors is incorrect. You should check the return value of fputs, and check if it's smaller than 0. If it is, then you can check errno to find out what caused the failure, but that's optional (and should be done before calling any further functions).

So, something like this should do the trick :

int result = fputs(buf, somefile);
/* optionally read errno here if result < 0 (before the free call) */
free(buf);
return (result < 0) ? -1 : 0;

Solution 2:

A POSIX compliant free might set errno today but this is going to change for the better in the future. Details:

  1. The The Open Group Base Specifications Issue 7 definition of errno states the following:

No function in this volume of POSIX.1-2008 shall set errno to 0. The setting of errno after a successful call to a function is unspecified unless the description of that function specifies that errno shall not be modified.

  1. The definition of free itself does not specify what free does with errno.

What this means is that a compliant free implementation will never reset errno to 0. But it may or may not set it to a non-zero value.

However, Issue 8 (a work in progress) of the specification will require free to specifically guarantee that it will not set errno when passed a valid input.

glibc is already gearing up to adhere to this new requirement.

Solution 3:

There is nothing said about errno in the description of free in the C Standard. So you may not rely on this feature.

According to the C Standard (7.5 Errors <errno.h>)

3...The value of errno may be set to nonzero by a library function call whether or not there is an error, provided the use of errno is not documented in the description of the function in this International Standard.

And the use of errno is not documented in the description of free in the C Standard as I have already said above.