Re: Difference between Macro and Function...

From: Eric Sosman (eric.sosman_at_sun.com)
Date: 10/21/04


Date: Thu, 21 Oct 2004 10:16:50 -0400

Chris Barts wrote:
> john blackburn wrote:
> |
> | free() is the companion function to malloc() and is definitely a
> function.
>
> Maybe, maybe not. It's up to the implementation.
>
> | Look up the library documentation; malloc is used to request memory space
> | and initialize a pointer to it and free() is used to release that memory
> | space.
>
> free() could be a wrapper around a function that programmers aren't
> supposed to call directly, or it might not use a function at all, just
> odd compiler magic.

    free() is always a function, in any conforming
implementation. free() may *also* be provided as a
macro, at the implementation's discretion, but it must
in any case exist as a function. The same is true of
all the other Standard library functions (other than
those "functions" that are specifically described as
macros, of course).

    The following program must compile and run:

        #include <stdio.h>
        #include <stdlib.h>

        static void do_it( void (*func)(void*), void *arg) {
            func(arg);
        }

        static void not_free(void *arg) {
            printf ("not_free: arg = %p\n", arg);
        }

        int main(void) {
            void *ptr = malloc(42);
            do_it (not_free, ptr);
            do_it (free, ptr);
            return 0;
        }

    This example is both contrived and pointless, but
it's not too hard to come up with a scenario in which
using a pointer to free() makes sense. At the risk of
straying from topicality, imagine a suite of programs
that share a single region of memory. The ordinary
malloc() and free() functions won't manipulate the
shared region, so you might well write shared_malloc()
and shared_free() with identical signatures and similar
semantics. Now, let's suppose you want to write a handy
function to release a linked list which might reside in
either shared or ordinary memory:

        void liberate_list(Node *list, void (*liberator)(void*)) {
            Node *head;
            while ((head = list) != NULL) {
                list = head->next;
                liberator (list);
            }
        }

Assuming that you know (somehow) whether the list is in
ordinary or in shared memory, you could write

        if (in_ordinary_memory)
            liberate_list (list, free);
        else
            liberate_list (list, shared_free);

... and the C Standard requires that the pointer to the
function free() work as expected.

-- 
Eric.Sosman@sun.com


Relevant Pages

  • Re: sizeof(ptr) = ?
    ... The value returned by malloc() is of type 'void*', ... The memory is typeless until an object has been written ... Since 'void' is defined to be an incomplete ... an lvalue of a complete type, there must be a pointer conversion ...
    (comp.lang.c)
  • Re: Checking validity of a file pointer
    ... because the pointer looks valid. ... detected (preferably by having fclose return an error indication ... if the buffer of the file is returned from the malloc() function, ... with memory returned from mallocfunction in that buff ...
    (comp.lang.c)
  • Re: memory allocation wrapper
    ... I've written a wrapper for malloc and friends. ... The reason for doing writing this so that newbies ... How do I know how much memory a pointer points to? ...
    (comp.lang.c)
  • Re: 2D array of structures
    ... Don't cast the return value of malloc(), ... you allocate here memory for 7 such structures. ... a pointer to the start of this memory, which is of type 'STRUCTURE *' ...
    (comp.lang.c)
  • Re: malloc does not return null when out of memory
    ... >> malloc() when the overcommitted memory is touched, ... >> touched it and there's no actual memory there. ... This patch does ... > 1) mallocreturning a pointer, and then sometime later the program dies ...
    (freebsd-stable)