The LuaTeX manual doesn't give much information on the precise details other than saying that one needs to ensure that there aren't any dangling pointers still referencing the node (location). For simple nodes that might be the case but already an adjust node made me question my understanding.

That type of node has a field head that points to another node holding the "vadjust" vertical list. So my simple minded assumption was that if I do

   local adjust = node.getfield(p, "head")   -- save the vlist

I'm fine, but as it turned out all pointers in my code got scrambled. Instead I first had to explicitly do

   node.setfield(p, "head", nil)

prior to freeing the node to prevent bad things from happening. What exactly goes wrong or what the function really does to the field value if it isn't nil I couldn't determine with trial and error.

So my question is: who can explain precisely what goes on with this command and/or where could one find out (i.e., where is its source assuming that is in a somewhat readable format)?

Another part of the question would be what happens when freeing other nodes that have similar structures, e.g., glue nodes (having a link to a glue-spec node etc)?

  • @barbarabeeton your finger prints are all over the place anyway (for example in the above comment) - thanks – Frank Mittelbach Oct 10 '14 at 21:33

This is an attempt to document how I understand it. It is not ment to be authorative or so. LuaTeX (the nodes-side) does not have any automatic garbage collection. If you lose a pointer to a node, it is lost in TeX's memory and eats up space. With node.free() you can free a node and all its children. That is, if you have a hlist node, node.free() will delete that node and the nodes of the list (its contents). It will not remove the next nodes in the current node list. Let me add a few examples:

Simple example

local a = node.new("glyph")
a.char = 97
local b = node.new("glyph")
b.char = 98

-- error: ! Attempt to double-free glyph (b) node 103, ignored.

this should be obvious. Freeing a node twice is not a good thing.

Warning. a still points to something. If you traverse the node list starting at a, LuaTeX will be upset.

A hbox with a glyph inside

hpack nodelist

local a = node.new("glyph")
a.char = 97
b = node.hpack(a)
-- ! Attempt to double-free glyph (a) node 97, ignored.

Here, a is one of the children of the node b, so a is removed from the memory when b is freed.

Glue and glue spec items

Now an example that is perhaps less obvious:

local spec = node.new("glue_spec")
spec.width = 1000
spec.stretch = 1

local a = node.new("glue")
a.spec = spec
local b = node.new("glue")
b.spec = spec
-- error:
-- ! Attempt to double-free glue_spec node 85, ignored.

Here again: node a is removed from memory, then the child spec is freed. Therefore (I find it somewhat surprising) b's child is removed from memory as well...

ligaturing (just two chars: f and i)

Before ligaturing:

before ligaturing

after ligaturing:

nodelist of ligaturing

local a = node.new("glyph")
a.char = 102
a.font = 15

local b = node.new("glyph")
b.char = 105
b.font = 15

a = node.ligaturing(a)

local c = a.components

node.free(a) removes the components, so removing c gives an error.

  • nice set of additional cases and their behavior, I still think it would great if we end up with an authirative answer (e.g., or in the manual) about which related sub-structured get freed, and which are left dangling in the memory and need explicit handling. As you said the glyph case, for example is a bit surprising (if not actually a bug, not sure "b" is removed or just needs its glue-spec first nil-ed before it can properly removed). Anyway, for now it is the best answer around ... though I think we can jointly improve on it :-) – Frank Mittelbach Jan 18 '15 at 20:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.