Hello
I'm trying to allocate scheme structures/records from C (without calling back to scheme). It's "basically" working but segfaults in the gc. What am I doing wrong?
Thanks Christian.
(declare (block) (standard-bindings) (extended-bindings))
(define-structure scheme-error code)
(c-declare " static ___SCMOBJ scheme_error_tag;
#include <stdio.h>
static ___SCMOBJ scheme_error(___SCMOBJ code) { ___SCMOBJ res= ___alloc_scmobj(___sSTRUCTURE, 3<<___LWS, ___STILL); if (___FIXNUMP(res)) { // alloc error printf("alloc error\n"); return ___FAL; } else { ___WORD*p= (___WORD*)___BODY(res); p[0]= scheme_error_tag; p[1]= code; ___still_obj_refcount_dec(res); return res; } } ")
(##c-code "scheme_error_tag=___ARG1;" (##vector-ref (make-scheme-error #f) 0))
(define call-scheme-error (c-lambda (scheme-object) scheme-object "scheme_error"))
#|
(compile-file "mailing-allocfromc")
#t
(load "mailing-allocfromc")
".../mailing-allocfromc.o1"
(call-scheme-error 100)
#<scheme-error #2 code: 100>
(define-macro (n-times* n proc)
(let ((PROC (gensym)) (N (gensym))) `((lambda (n proc) (let lp ((i 0) (r #!void)) (if (>= i n) r (lp (+ i 1) (proc i))))) ,n ,proc)))
(n-times* 1 call-scheme-error)
#<scheme-error #3 code: 0>
(n-times* 1 call-scheme-error)
#<scheme-error #4 code: 0>
(n-times* 100 call-scheme-error)
#<scheme-error #5 code: 99>
(n-times* 100000 call-scheme-error)
Program received signal SIGSEGV, Segmentation fault. [Switching to Thread -1214988160 (LWP 15668)] mark_array (start=0x8253b98, n=1) at mem.c:1750 1750 head = body[-1]; (gdb) bt #0 mark_array (start=0x8253b98, n=1) at mem.c:1750 #1 0xb7cd65a1 in scan (body=0x8253b90) at mem.c:2254 #2 0xb7cd661f in scan_still_objs_to_scan () at mem.c:2290 #3 0xb7cd7620 in ___garbage_collect (nonmovable_words_needed=0) at mem.c:3626 #4 0xb7cefd67 in ___H__20___kernel (___ps=0xb7f5c320) at _kernel.c:7301 #5 0xb7cd42db in ___call (nargs=0, proc=-1209590511, stack_marker=136566237) at setup.c:1779 #6 0xb7cd527e in ___setup (setup_params=0x0) at setup.c:2909 #7 0xb7cd29c8 in ___main (linker=0xa0a2928) at main.c:557 #8 0xb7cdd4a9 in ___main_char (argc=6, argv=0xa0a2928, linker=0xa0a2928, script_line=0xa0a2928 <Address 0xa0a2928 out of bounds>) at os_base.c:240 #9 0x0816207f in main () (gdb)
|#
Afficher les réponses par date
At 18:36 Uhr +0100 05.11.2006, I wrote:
It's "basically" working but segfaults in the gc. What am I doing wrong?
I think I have found the reason: I've put a pointer to a movable objects into still objects.
I'm now in the process of writing a recursive ##still-copy routine (so that I can store away a reference to a still object into C space instead; well maybe there's also a make-structure internal routine that accepts a still flag?).
Christian.
Out of curiosity, why are you doing so much work on the C side, rather than letting Scheme control everything? You could return an integer to Scheme here, which Scheme code could then wrap in the structure; it seems awfully indirect and a great deal more work than it's worth to do it from C, but perhaps I'm missing a better reason here.
At 0:12 Uhr +0000 06.11.2006, Taylor R Campbell wrote:
Out of curiosity, why are you doing so much work on the C side, rather than letting Scheme control everything? You could return an integer to Scheme here, which Scheme code could then wrap in the structure; it seems awfully indirect and a great deal more work than it's worth to do it from C, but perhaps I'm missing a better reason here.
The reason is returning errors.
One can only return one value from C (except that c-lambda offers an error reporting mechanism, see below), and if the normal value is to be the whole range of a fixnum, there is no space to return an error number (just returning e.g. #f cannot tell which error happened). Now I could allocate a data structure in scheme and pass this to C to be mutatet and returned from there in the case of an error, but that would cost a memory allocation also in the non-error case.
c-lambda offers ___err to return errors, but it doesn't seem extensible (it's based on globally predefined fixnum values; there is the possibility to return arbitrary string messages, but I think then the exception values are not typed anymore, which would be necessary to be able to catch them selectively).
##c-code is faster (no overhead at all) than c-lambda (about 50 cycles), probably mostly because c-lambda is setting up the scheme environment so that C code can call back to scheme(*), which is not possible from ##c-code. That's why I've been asking for a solution which doesn't need a callback to scheme to allocate a structure.
(*BTW Marc: would it be possible to do this setup step only when needed, kind of lazily?)
Christian.