[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: hashx -set! and -ref
From: |
Gregory Marton |
Subject: |
Re: hashx -set! and -ref |
Date: |
Sat, 12 Jan 2008 06:37:31 -0500 (EST) |
So this seems to crash inside scm_hash_fn_set_x:
in libguile/hashtab.c:510:
SCM
scm_hash_fn_set_x (SCM table, SCM obj, SCM val, unsigned long (*hash_fn)(),
SCM (*assoc_fn)(), void * closure)
{
SCM it;
it = scm_hash_fn_create_handle_x (table, obj, SCM_BOOL_F, hash_fn, assoc_fn,
closure);
SCM_SETCDR (it, val);
return val;
}
as indicated by:
[trinidad installing-guile/guile-1.8.3]$ gdb libguile/.libs/guile
GNU gdb 6.4.90-debian
Copyright (C) 2006 Free Software Foundation, Inc. [...]
This GDB was configured as "i486-linux-gnu"...Using host libthread_db
library "/lib/tls/libthread_db.so.1".
(gdb) run -l ht.scm
[which contains:
(hashx-set! (lambda (k s) 1) (lambda (a b) #t) (make-hash-table) 'foo 'bar)
]
Starting program:
/afs/csail.mit.edu/u/g/gremio/installing-guile/guile-1.8.3/libguile/.libs/guile -l ht.scm
Failed to read a valid object file image from memory.
[Thread debugging using libthread_db enabled]
[New Thread -1211361600 (LWP 28295)]
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread -1211361600 (LWP 28295)]
0xb7f008da in scm_hash_fn_set_x () from /usr/lib/libguile.so.17
(gdb) bt
#0 0xb7f008da in scm_hash_fn_set_x () from /usr/lib/libguile.so.17
#1 0xb7f00942 in scm_hashx_set_x () from /usr/lib/libguile.so.17
#2 0xb7efdd5d in scm_gsubr_apply () from /usr/lib/libguile.so.17
This means to me that
(define table (make-hash-table))
(hashx-create-handle! (lambda (k s) 1) (lambda (a b) #t) table 'biz 'buzz)
should not crash, and indeed, it returns #t.
It doesn't help the problem that the association fails, and I wonder if
that's because the hash_fn is supposed to be unsigned long (*hash_fn)().
How does one create one of these in user space? (lambda (k s) 1) is
something more like SCM (*hash_fn)() ?
So if I pass in something that returns scheme objects instead of unsigned
longs, and they get interpreted as unsigned longs, then no wonder I don't
find the key next time. I might be deeply misunderstanding things though.
As another question, when I hash things using hashx-set! and later the
table needs to be resized, is it the closure that's supposed to remember
what function I hashed that key with? I just added a test for this
(enclosed), and despite no segfaults, the test fails -- the hash seems to
forget about some of its items after resizing.
As a design decision, most hash implementations I've seen, if they allow
your own hash function at all, they ask you to specify it at hash creation
time, and they usually do the modulo themselves (so the hash function is
one-argument). The spec for guile seems to be somewhat more flexible, but
at the expense of a fair bit more overhead required to keep things straight
during resize. That is, in a sane implementation, you'd have to remember
the hash function used to put each key in, so you'd have some hope of
getting it back out again. Why did guile choose to spec this way?
Thanks in advance for any input,
Grem
Enclosed is a patch for test-suite/tests/hash.test that contains, among other
things, the segfaulting behavior.
Best,
Grem
I managed to compile 1.8.3 on debian and it shows much the same error,
substituting a Segmentation Fault for bus error in the last case.
Guile 1.3.4 simply returns #f in both cases.
I'm inclined to start poking at guile's source code for the first time.
Could someone give me helpful pointers in the right general direction?
Thanks,
Grem
On Thu, 10 Jan 2008, Gregory Marton wrote:
I may be misunderstanding something, but I thought this should yield 'bar:
guile> (let ((ht (make-hash-table)))
(hashx-set! (lambda (k s) 1) equal? ht 'foo 'bar)
(hashx-ref (lambda (k s) 1) equal? ht 'foo))
#f
guile> (version)
"1.8.1"
much as this does:
guile> (let ((ht (make-hash-table)))
(hash-set! ht 'foo 'bar)
(hash-ref ht 'foo))
bar
I thought perhaps the problem was with the equality test somehow, but then
even worse:
guile> (let ((ht (make-hash-table)))
(hashx-set! (lambda (k s) 1) (lambda (a b) #t) ht 'foo 'bar)
(hashx-ref (lambda (k s) 1) (lambda (a b) #t) ht 'foo))
Bus error
Thanks much,
Grem
p.s. Ludovic, I haven't forgotten about the module docs -- it's just
taking me a while to learn what I need. Sorry.
--
------ __@ Gregory A. Marton http://csail.mit.edu/~gremio/
--- _`\<,_ .
-- (*)/ (*) The prime number few.
~~~~~~~~~~~~~~~~-~~~~~~~~_~~~_~~~~~v~~~~^^^^~~~~~--~~~~~~~~~~~~~~~++~~~~~~~
hash.test.patch
Description: Text document