Custom Malloc() Function :: What Does this Syntax Mean?

353 views Asked by At

I am writing a C program with the nDPI library, available here. (Coding on a Ubuntu machine, GCC compiler, nDPI version 3.2) nDPI is used to inspect network traffic. The code uses a lot of different structs to represent network stuff, like network flows, network protocols, network hosts, and so on.

So I think that if you want to create these structs, you must use the library's custom malloc() and free() functions, which makes sense. But I'm having a hard time understanding the function prototypes. Here's a few relevant lines of code from the API header file:

/* Utility functions to set ndpi malloc/free/print wrappers */

void set_ndpi_flow_malloc(void* (*__ndpi_flow_malloc)(size_t size));

void set_ndpi_flow_free(void (*__ndpi_flow_free)(void *ptr));

Consider the set_ndpi_flow_malloc() function. Elsewhere in the source code, there is a struct nDPI_flow_info defined, and I see that struct used everywhere in the code. So I assume set_ndpi_flow_malloc() is to allocate one of these structs on the heap, populate it with some information maybe, and return the pointer.

But I don't understand the arguments into this function. If I had to guess, I'd say that set_ndpi_flow_malloc() accepts a pointer to another function, called __ndpi_flow_malloc(), and that function takes a size_t integer as an argument. Turns out, there's this function prototype elsewhere in the API header file:

void * ndpi_flow_malloc(size_t size);

That's kind of the function I need: I need __ndpi_flow_malloc() (two underline characters on the front of the name) What do those double underlines mean?

Another question... if set_ndpi_flow_malloc() is a custom malloc() function, shouldn't it return a pointer to the allocated memory?

Another question... How would I actually write this in my code? Like this...?

struct nDPI_flow_info* myFlow;

set_ndpi_flow_malloc( (void*) &ndpi_flow_malloc( sizeof( struct nDPI_flow_info )) );

// ...use the struct...

set_ndpi_flow_free( &ndpi_flow_free* myFlow ) );

That can't be right. I don't understand how the second line returns the pointer and assigns it to variable myFlow.

Any advice or criticism is wildly appreciated. Thanks!

FULL DISCLOSURE :: I have also posted this question here.

2

There are 2 answers

0
dbush On BEST ANSWER

The function set_ndpi_flow_malloc doesn't actually do the allocation but allows you to set the function that does. It's argument is a pointer to a function that takes a size_t and returns a void *, and the name of the argument is __ndpi_flow_malloc.

The same goes for set_ndpi_flow_free. It tells the library which function to use as its custom free function.

Most likely, ndpi_flow_malloc is the default custom allocator. So if this is the one you want to use you would do the following to set it as the custom allocation function:

set_ndpi_flow_malloc(ndpi_flow_malloc);

Then assuming there is a similar default free function called ndpi_flow_free, you would do this to set it as the custom free function:

set_ndpi_flow_free(ndpi_flow_free);
1
John Bode On

I'm not familiar with this API, but based on what you've posted here it must allocate memory internally to perform some operations, and it allows you to specify which allocator/deallocator it should use to do that - it can either use vanilla malloc and free to allocate and deallocate memory, or you can pass a custom allocator/deallocator that uses a different allocation scheme or is instrumented for logging/debugging or whatever.

To make this easier to read, I'm going to rename things. Basically pretend I've done

#define SNFM set_ndpi_flow_malloc
#define NFM  __ndpi_flow_malloc

That leaves us with

void SNFM(void *(*NFM)(size_t size));

which is read as

     SNFM                               -- SNFM
     SNFM(                         )    -- is a function taking
     SNFM(        NFM              )    --   parameter NFM
     SNFM(      (*NFM)             )    --   is a pointer to
     SNFM(      (*NFM)(           ))    --     a function taking
     SNFM(      (*NFM)(       size))    --       parameter size
     SNFM(      (*NFM)(size_t size))    --       is a size_t
     SNFM(     *(*NFM)(size_t size))    --     returning a pointer to
     SNFM(void *(*NFM)(size_t size))    --       void
void SNFM(void *(*NFM)(size_t size));   -- returning void

So basically, the argument to set_ndpi_flow_malloc is a pointer to a function that takes a size_t and returns a pointer to void - i.e., malloc or a function with the same signature that does the same thing:

set_ndpi_flow_malloc( malloc );

or

void *my_malloc( size_t size )
{
  ...
}
...
set_ndpi_flow_malloc( my_malloc );

This function doesn't allocate memory; instead, it's how you specify which allocator to use when the library needs to allocate memory internally. set_ndpi_flow_free does the same thing with the deallocator - you can either use the vanilla free from the standard library, or pass a custom deallocator:

set_ndpi_flow_free( free );

or

void my_free( void *ptr )
{
  ...
}
...
set_ndpi_flow_free( my_free );