So many different mallocs - do we need them?

I have a really odd problem that I described here. I try to get my head around this issue and came across this in memory.h:

#define NEW(t)           (t*)zmalloc(sizeof(t))
#define N_NEW(n,t)       (t*)gcalloc((n),sizeof(t))
#define GNEW(t)          (t*)gmalloc(sizeof(t))

#define N_GNEW(n,t)      (t*)gcalloc((n),sizeof(t))
#define N_GGNEW(n,t)      (t*)calloc((n),sizeof(t))

and later:

extern void *zmalloc(size_t);
extern void *zrealloc(void *, size_t, size_t, size_t);
extern void *gcalloc(size_t nmemb, size_t size);
extern void *gmalloc(size_t);
extern void *grealloc(void *, size_t);

I am not really into this memory allocation business (spoiled by the likes of Java and Swift), but what are we doing here? Why so many new versions? Why always so inspirational names? :slight_smile: Can these even work with each other? Should we try to harmonise?

1 Like

realloc/calloc/malloc do different things. I’m not sure about the other letters in front of the names or the macros though.

It’s not so important. The meaningful problems are bugs in spline routing, orthogonal edge routing, the “trouble in init_rank” that would not die, lack of object classes in the graph language, and one or two outstanding CERT advisories. That weird bug with ports on record nodes being flipped in certain left-to-right layouts Incrementally stable layout in dotgen, Can gvedit make the jump to QT6. New algorithms that could help with untangling hairballs. These are interesting topics.

Stephen, could you elaborate on “lack of object classes in the graph language”. What kind of classes? Do you mean like style attribute classes (like CSS classes) that are shorthand for a set of attributes?

Agree it’s not that important to reduce the number of mallocs used.

It’s not even different mallocs - I think they are just macros or functions that wrap whatever malloc is around.

I realize that reliance on macros is passe and out of step with reasonable coding style today.

The idea was to someday support classes, like

    node myclass [shape=box, style=filled, fillcolor=lightblue]
    node myotherclass [fillcolor=palegreen,fontname=Helvetica]
    somenode [myclass, myotherclass]

There would need to be a dict of dicts for each graph object type in each graph/subgraph. There would need to be functions for operating on them.

Some thought would have to be given to how to write the graphs correctly.

It might be easier to at first consider classes to be immutable after they’re defined.

I will respectfully disagree with Stephen :slight_smile:

Vithanco, my background is mostly C/C++ and I still had a very similar reaction to you when learning the code base. In 2020 I deleted as much of lib/vmalloc as I could and tried to reduce other malloc duplication across the tree. Let me try to answer your questions…

Some of these have slightly different purposes. There’s the three library functions Mark noted, then the “g” prefixed wrappers that exit on failure and the “z” prefixed ones that return pre-zeroed memory. As for why the macros like N_NEW are repeated in various parts of the code base, I assume when this code was written #includes were somehow expensive and to be avoided.

My interpretation of the prefixes is “g/G” = “global”, “N_” = “new”, “z” = “zeroing”. This is terse, but pretty common in C code bases. I’ve seen the same named functions elsewhere.

Yes. They all allocate from the same heap, with the exception of lib/vmalloc (“vm” prefixed functions) which is an arena allocator. In the long term I would like to remove it completely.

Maybe. Some of these wrappers are useful. E.g. the zmalloc wrapper helps write more readable code. The “g” prefixed wrappers are also useful because many Graphviz allocations do not check the return value. None of this is really good practice, but we have to deal with the situation as it is.

I like that, @scnorth. That is exactly what I do with Vithanco. I create Node Types, and I even define which type can be connected to which other Node Types, hence I create a Meta model for my graph.

I found it very useful to have the Node Type name in the node, I use that in most meta models. Here an example from the Benefit Breakdown Structure (Domain)

And yes, I use Graphviz for the layout, I just draw the nodes myself.

I think that class syntax could really help for the usecase of technical graphs checked in to documentation. Some of it we can achieve with CSS on generated SVG but not all. We have the “class” attribute that we might want to reuse to avoid users naming their own attributes that might conflict with future attributes?