-1

I am not asking if I need to check to see if a pointer is NULL before calling free, I know I do not. Rather, I am asking whether a (typical) implementation of free sacrifices time to check for a NULL pointer before deallocating, or whether the nature of the process does not actually invoke any additional overhead. For example, someone knowing what free does might imagine that its implementation might be something like this:

void free(void* ptr){
    if(ptr != NULL){
        <proceed with deallocation>
    }
}

But this contradicts the C philosophy of not paying for what I don't use: if I know I will not pass a NULL pointer to free, there should not be a performance deficit as a result. Thus, I am pretty sure that free does not usually invoke such a cost, and in that case I would like to know how/why. I tried searching for the answer to this but I saw a hurricane of questions asking whether deleting a NULL pointer was safe instead.

EDIT: I am already satisfied with the answers and comments, though for future reference I want to make clear what it is I was asking. I was not asking from a programmer's perspective what the state of the program and my NULL pointer are after I call free on it. I was more interested in the perspective of the heap manager. To give an example of what I mean, suppose I am at a bakery and it is my job to take whatever is at the table and dump it all in the trash. It could be 5 brownies, a dozen cookies, or whatever, and yes I know this is not the best analogy but bear with me. I wanted to know if there could exist heap managers that, if for instance, there was "nothing" on the table whether my dumping "nothing" into the trash would make any difference, which would be an implicit handling of "nothing." An explicit handling of "nothing" would be my checking of the table to see if anything is on it before I try to dump it. I wanted to know if heap managers could usually handle the situation implicitly, i.e., by doing the same thing that they would normally do and incidentally also handling a NULL pointer, or explicitly, by making an explicit check to see if a pointer is NULL. As awksp's comment reveals, since it is required that nothing literally be done in the case of a NULL pointer, it must be true that an explicit check exists because treating the NULL pointer the same as the others would not be a no-op, and therefore we must check for NULL explicitly beforehand.

user1609012
  • 191
  • 8
  • 1
    Compared to the other "overhead" for proper heap management, any check will be neglectible. If you are up for speed, do not use the standard functions. And your claim "of not paying for what I don't use" is only valid for the language itself. It is actually not to add unavoidable overhead. But library functions can be replaced by custom versions. Just think of `printf`. – too honest for this site Sep 07 '15 at 00:07
  • Is the question _that_ dumb? I don't think I'm asking what you guys think I'm asking :(. – user1609012 Sep 07 '15 at 00:08
  • Which "guys"? Last time I tralked to myself, I was not schizzo. For the question: I'd prefer to say it is badly researched ... – too honest for this site Sep 07 '15 at 00:09
  • I wasn't referring to you haha. – user1609012 Sep 07 '15 at 00:09
  • I do not see anyone else commenting. – too honest for this site Sep 07 '15 at 00:10
  • I'm addressing down-voters, not commenters – user1609012 Sep 07 '15 at 00:11
  • A short search would have given you the answer: http://port70.net/~nsz/c/c11/n1570.html#7.22.3.3 So, be there overhead required or not, it has to be accepted. – too honest for this site Sep 07 '15 at 00:13
  • 1
    It doesn't say anything about performance: I guess I'm architecturally naive, but it is so hard to believe that a heap management system operating on a `NULL` pointer could cause nothing to happen without explicitly doing a `NULL` pointer check? I am basically asking if `NULL` is actually handled as a special case or whether such code actually has no effect on `NULL`. Man I dunno, it just seems inconsistent to me that a `vector` won't throw an exception from index out of bounds but `free`, something I would consider to be more primitive, does a safety check. – user1609012 Sep 07 '15 at 00:18
  • Please read the link! If you do not understand, step back and read a tutorial or C book. The standard does not make any assumtions about performance, btw., how checks are performed, etc. And C does not have `vector`s or exceptions. And C11 does provide a bounds checking interface. If you really think `free` is trivial, you really should read more. – too honest for this site Sep 07 '15 at 00:21
  • Yes I understand which is why I specified that I was wondering about _typical_ implementations. Is there more in the link you suggested I read besides the definition of the free function? It says how `free` behaves, and yes, you are right, I am asking more of an architectural implementation question than a C question. And by primitive I do not mean trivial, I mean closer to low level. I am referring to C++ vectors and C++ prescribes a similar philosophy to C. – user1609012 Sep 07 '15 at 00:25
  • [The glibc free() implementation](http://code.woboq.org/userspace/glibc/malloc/malloc.c.html) does `if ( mem == 0 ) return;`. I guess if this "waste of time" really bothers you, you could write your own allocator ... – M.M Sep 07 '15 at 01:00
  • 3
    See [here](https://stackoverflow.com/questions/1938735/does-freeptr-where-ptr-is-null-corrupt-memory). tl;dr the ISO standard requires free(NULL) to be a no-op. So I guess the answer is yes? – awksp Sep 07 '15 at 01:01
  • Thank you for answering my question :), I guess that means it must do a check for any implementation? And by the way, I was asking out of curiosity not practicality, it seemed uncharacteristic of C to me. I certainly have never had a program where I was actually _worrying_ about the performance cost of free haha. – user1609012 Sep 07 '15 at 01:16

3 Answers3

2

Here's why checking for NULL in free() is more than just a nice idea:

When you use malloc(), you don't have to remember how much memory you asked for: The heap manager does that for you. So, when you free a block, it's got to add the freed block (of the correct size) into whatever data structures it uses to hold this information.

So, how could it know the size? It could find the pointer in some other structure containing lists of all the allocated memory, but without some kind of Content-addressable-memory hardware, that's likely to be slow. So intead, most heap managers use a trick of storing metadata about the block that you were allocated in memory immediately before the pointer they give you. (it can't be at the end of the block, because remember we don't know the actual block size...)

If the heap manager doesn't explicitly check for NULL, it will start trying to access memory at negative addresses (eg. NULL-16), which is likely to cause access violations and all sorts of other undesirable effects. MUCH better to have a trivial (if x=NULL) before the start.

Does it cause a performance hit? Possibly, but it's totally trivial compared to all the block merging, list searching, etc. that are all needed in typical heap managers.

Roddy
  • 66,617
  • 42
  • 165
  • 277
  • Are these problems that would occur worse than the problems associated with double freeing a pointer? – user1609012 Sep 07 '15 at 18:15
  • @user1609012. I'd expect that free that didn't check for NULL would crash instantly, while double-freeing could crash immediately, in a week, or not at all. It could also corrupt data. But the standard specifies that freeing NULL is harmless because it's a common "mistake" and it's trivially easy to check for. Checking for double-frees would be an incredible overhead. – Roddy Sep 08 '15 at 12:18
1

actually what free does is just giving the allocated memory block ( if there is any ) back to your operating system whether it is allocated using malloc or realloc or whatever, there should be a pointer to the start of the block and the length of the block saved somewhere . it has obviously ( in most platforms ) the overhead of 8 byte for each byte allocated , which is a great overhead ( in terms of memory usage ) but it is what operating systems does in reality .

so talking about ANSII C when there is a null pointer passed to the free function according to what said above will do nothing because it points to no block of memory , so as long as it does nothing underneath the hood it will produce a time overhead .

the malloc and free implementations are always one of the biggest problems for who developing operating systems . so i will suggest to implement them once for yourself then try if you can reduce the overheads as much as possible .

Mohammad Siavashi
  • 1,192
  • 2
  • 17
  • 48
1

First - calling free() on a null pointer doesn't really do anything. You don't need to check, you are covered in the case of a zero.

Second - on any modern system, checking a pointer before using it will have tiny overhead, maybe even a single clock cycle, which is literally negligible, so don't hesitate - check when there is need to. Not in the case of free() but there are numerous cases where you'd want to check.

The pointer will have to reach a CPU register before used, so an extra check for null will be very efficient. It is nothing compared to fetching data from ram or thread context switching.

dtech
  • 47,916
  • 17
  • 112
  • 190