[gambit-list] strange mutation problem (bug?) (Re: "Number of arguments exceeds implementation)

Marc Feeley feeley at iro.umontreal.ca
Fri Sep 29 07:27:57 EDT 2006


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 29-Sep-06, at 4:34 AM, Christian wrote:

> At 1:17 Uhr -0500 29.09.2006, Bill Richter wrote:
>> Christian suggested I might have found a real bug,
>
> The interesting bit is, that using compile-file & load Bill's program
> usually works, whereas with static compilation/linking not. I don't
> know where Gambit would differ in those two
>
>> and that I should
>> try stripping off as much fat as possible from my program.
>
> You should strip it more until you can say "if I leave this out, it
> doesn't do weird things anymore".
>
> Here's what you should be doing in such cases:
>
> * check which functions are really mutating, and which ones are
> functions. I realize that you're using map (meant for functions)
> where I think for-each (meant for imperative code) is what you want
> (maybe the order of evaluation may be a problem!). I realize that
> UnSpace clearly does mutate it's argument, thus rename it to UnSpace!.
>
> * try to find out whether ShowPossibilities mutates it's argument.
>  From a quick look at the code, I'd say so, but runnning it in gsi, I
> couldn't find a modification of it's input, strange.
>
> * try to find out where during the runtime of the program the problem
> happens. For this, outputting the relevant datastructures helps. I've
> put a (pp U7) between the two ShowPossibilities calls and another one
> after the second. After the first ShowPossibilities call U7 is
> containing lists (is this what you want?); then the second
> ShowPossibilities call runs into the error. So clearly U7 has been
> modified, and ShowPossibilities should be renamed to
> ShowPossibilities!.
>
> Why does the same not happen in the interpreter? Before knowing that
> it's a Gambit bug, we have to rule out that it's from a difference
> between interpreter and compiler behaviour.
>
> Trimming it further down for an hour, I realize that you're modifying
> quoted datastructures. IIRC, R5RS says that modifying constant
> datastructures is undefined, and Gambit seems to rely on them not
> beeing modifyed when compiling to static binaries.
>
> Replace all quoted #(..) with (vector ..) and it works.
>
> Christian.

Nice debugging Christian!  Yes the problem comes from mutation of  
constants.  It works in the interpreter because the interpreter does  
not create constants for quoted objects (the constant is created by  
the reader):

 > (define (f)
     (let ((x '(111)))
       (set-cdr! x (cons (car x) (cdr x)))
       (length x)))
 > (f)
2
 > (f)
3
 > (f)
4
 > (pp f)
(lambda ()
   (let ((x '(111 111 111 111)))
     (set-cdr! x (cons (car x) (cdr x)))
     (length x)))

If you try compiling this kind of code you will have problems because  
the garbage collector does not traverse constant objects (because  
they can only contain references to other constant objects, and they  
are "permanently" allocated).

I'm thinking of adding a run time check to set-c[a|d]r!, vector-set!,  
etc to verify that the object is mutable.  This can be done quickly  
by checking if the object is a ___PERM object.

By the way, statically linked programs and those produced by compile- 
file should behave the same.

Marc

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.3 (Darwin)

iD8DBQFFHQM9//V9Zc2T/v4RAu/oAJ48h0XcEs0y1W8YI6djFBvimHr6mACgq1ji
qJ9UZrnbHDFoZnT/CV/OlGA=
=PfMd
-----END PGP SIGNATURE-----



More information about the Gambit-list mailing list