Although this is a well constructed question I must say it is a little difficult to know exactly what you're looking for. Is it a semantic error?
However to try and give you some perspective; for one thing you aren't properly freeing 6 blocks of memory,
total heap usage: 8 allocs, 2 frees, 1,472 bytes allocated, "still reachable" implies that the memory requested is not freed, although it is really not necessary to free those blocks since they are allocated near-termination of your program, so the OS will reclaim the memory very soon. See this answer on SO.
Your valgrind call spits out a lot of information not (necessarily) applicable to your case, line 45 and downwards to 76 spits out memory redirects between function calls, called a traceback or stack trace, this is a result of the
--memcheck:track-origins=yes flag included. From line 12 up until line 76 "syms" or "symbol table" is mentioned frequently, the symbol table is a data structure that defines what variables were declared where and the scope they belong to.
This answer is admittedly very generic and won't directly solve your problem, but without a clue of what the problem is, I'm sorry to say I cannot say how to solve it. I hope at least it will guide you the right way, good luck!
Edit: I see you posted your actual code while I was typing this answer, I have to go now but I'll see if I can get look at it later if no one else replies.
Something is not being freed in load() at line 89 according to valgrind at line 112. That is the only thing not being freed according to valgrind at line 110 "loss record 1 of 1".
This is now getting me thinking whether or not I have free'd in the wrong order or not
As long as you didn't free anything you really shouldn't in load() you're probably clear on that end. In unload(), according to valgrind, you free everything you once allocated.
Edit: Actually, since the memory allocated in load() shall be freed in unload() you might indeed have a leak, I'll look over your code.