bug-guile
[Top][All Lists]
Advanced

[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~~~~^^^^~~~~~--~~~~~~~~~~~~~~~++~~~~~~~

Attachment: hash.test.patch
Description: Text document


reply via email to

[Prev in Thread] Current Thread [Next in Thread]