Closed canadaduane closed 10 years ago
Narrowed the cause down to a null node or stack:
static void hattrie_iter_nextnode(hattrie_iter_t* i)
{
if (i->stack == NULL) return;
/* pop the stack */
node_ptr node;
hattrie_node_stack_t* next;
unsigned char c;
size_t level;
node = i->stack->node;
at this point, node is 0 (NULL).
Or rather, node.flag is NULL:
node = i->stack->node;
next = i->stack->next;
c = i->stack->c;
level = i->stack->level;
free(i->stack);
i->stack = next;
assert(node.flag != NULL);
if (*node.flag & NODE_TYPE_TRIE) {
Assertion failed: (node.flag != NULL), function hattrie_iter_nextnode, file ../hat-trie/hat-trie.c, line 565.
Thanks for reporting, I'm looking into it.
Not sure if this is helpful, but I commented out node.flag = NULL;
on line 127 of hat-trie.c and found that the segfault is fixed. However, searching a Triez with more than 16,384 nodes will return zero results (<=16,384 nodes does return results)
Any further progress? I'm still trying to track it down. If you have any ideas, I'd be happy to hear and possibly help (I'm still trying to understand how it all works, however).
Sorry for the late response. I got other work to do in the last days... Now I'm looking back this.
The flag
field is the first byte in tree_node_t.xs
, which tags whether the node has value, and the type of the data chunk. The types are:
xs
is serialized string postfix and valuesxs
is serialized bucket, but mapping character ranges to valuesxs
is an array of nodes, xs[character] = value
The logic inside is quite complex...
Seems hattrie_find(hattrie_t* T, const char **key, size_t *len)
has set the flag to NULL
due to some unkown reason? I'm still looking...
I got it. It is because I hattrie_find()
sets node.flag = NULL
for nodes that doesn't contain value
, I reused it for prefixed-iteration without aware of that field could be NULL! Thanks very much for finding it out!
The fix: https://github.com/luikore/hat-trie/commit/85bb89464a6a4be10b3f7449a69c75d463f52098
I'm bumping a new version for the gem, plz see if it works :)
If you are compiling from source, plz run rake glob_src
again.
So this appears to fix the segfault, but it returns incorrect data. i.e. it doesn't return any data for >16,384 nodes:
require 'triez'
t = Triez.new
3.times{ |i| t["a#{i}"] = rand(10)+1 }
p t.search_with_prefix("a")
# [["1", 2], ["2", 3], ["0", 3]]
require 'triez'
t = Triez.new
16_385.times{ |i| t["a#{i}"] = rand(10)+1 }
p t.search_with_prefix("a")
# []
Sorry, my bad for not checking further correctness. Just pushed the fix: https://github.com/luikore/hat-trie/commit/4556cf4e7fcf890c5a53dd7c29b615311cebeead
hope it works :hourglass:
Awesome! Looks great here. [SNIP: moving other comments to separate issue]
:)
I'm running on Mac OS 10.9.4 with ruby 1.9.3p194. If I run the above with
16_384.times
all is well.16_385.times
yields the following: