Does free() set errno?

CLinuxMemory Management

C Problem Overview


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));
}

C Solutions


Solution 1 - C

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 - C

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 - C

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.

Solution 4 - C

If the reference doesn't say that a function returns an error code in errno on failure, it won't.

Functions that set errno to an error code (almost) always signal in another way that errno contains the current error code - the memory allocation functions return NULL, many other functions return zero or a negative number, and so on.
Such functions are not required to modify errno in any way if they succeed, and usually don't.

You usually can't inspect errno to determine whether something went wrong; it is only meant for retrieving more information once you know that there has been an error.

One exception to the final rule is the strto{l, d, ul} family, but the first paragraph is true for those as well.
And they also don't necessarily set errno except when they fail, so you need to clear it first or it may contain a stale error code.

Solution 5 - C

Yes free() may clobber errno on various systems. gnulib avoids this issue by replacing free() on such platforms, which it documents currently as: "glibc 2.32, Mac OS X, FreeBSD, NetBSD, OpenBSD 4.4, Minix, AIX, HP-UX, IRIX, Cygwin, mingw, MSVC"

Solution 6 - C

you can use RAII to free malloced memory, and check the return value of fputs. That will be grace code.

//if malloc successfully
AutoFree af(buf);
if (fputs(buf, somefile)) {
LOG("something err:%s", strerror(errno));
}
return 0;

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPaulView Question on Stackoverflow
Solution 1 - CSander De DyckerView Answer on Stackoverflow
Solution 2 - CArjunShankarView Answer on Stackoverflow
Solution 3 - CVlad from MoscowView Answer on Stackoverflow
Solution 4 - CmolbdniloView Answer on Stackoverflow
Solution 5 - CpixelbeatView Answer on Stackoverflow
Solution 6 - Cuser4531555View Answer on Stackoverflow