gerbil
gerbil copied to clipboard
Safer defaults for make-vector, make-string, make-u8vector, and so on
The optional fill
argument should not default to "contents are unspecified", but either #f
or 0
or null or whatever makes the most sense for each datatype.
These can be wrappers over the Gambit functions, where the raw "contents are unspecified" behavior can be exposed in either unsafe-
variants or ##
prefixes.
Yeah, this makes sense. For the numeric vector the default of 0 is fine, but for the other vectors we need saner defaults.
The simplest way to implement this is to redefine the primitives in the runtime (in gx-gambc0) to something like this:
(define (make-vector len #!optional (fill #f))
(##make-vector len fill))
When we get contracts, we can also some contract protected checks for the len being a positive fixnum, but we can avoid it for now as it will have a slowdown effect.
The other thing we will need to do will be to also tell the compiler to inline it (make-vector len)
to (##make-vector len #f)
, which again will get some contract gating later.
This can be done in src/gerbil/prelude/core.ssxi.ss
(also the bootstrap version).
@AlexKnauth can you provide an example of the current behaviour? From what I see, only the return value is unspecified in some cases (subvector-fill!
, substring-fill!
).
> (make-vector 10)
#(0 0 0 0 0 0 0 0 0 0)
> (make-vector 10)
#(0 0 0 0 0 0 0 0 0 0)
> (make-vector 10 #f)
#(#f #f #f #f #f #f #f #f #f #f)
> (make-u8vector 10)
#u8(0 0 0 0 0 0 0 0 0 0)
> (make-u8vector 10 9)
#u8(9 9 9 9 9 9 9 9 9 9)
I cannot find where it says "contents are unspecified" in the doc. Unless I'm misunderstanding, @vyzo 's solution does exactly what the Gambit primitives already do.
The examples of unpredictable behavior don't always happen. I don't know exactly what causes the contents to be non-zero, but I suspect it has something to do with the interactions of the allocator and garbage collector with the operating system. This means that it can behave differently on different operating systems, and behave differently under different levels of memory-stress.
Ah! That's a bug to be filed in Gambit then! So somehow your returned vector contains garbage? If so, then vyzo's solution wouldn't change a thing.
Do you have any way to reproduce this, even probabilistically?
So somehow your returned vector contains garbage? If so, then vyzo's solution wouldn't change a thing.
What do you mean? The returned vector will only contain garbage if the fill
argument to the Gambit vector constructor is left out. When the fill
argument is supplied, the vector's contents are exactly as you'd expect, so Vyzo's solution would fix it.
That is concerning. Does it happen with small or large vectors? Which kind of vector?
It's happened to me on 1-element vectors through 32-element u8vectors, but I can't always reproduce the non-zero contents in self-contained toy examples.
Ok, if you are using (declare (not safe))
, then an undefined fill
argument is probably the culprit. ##make-u8vector
won't initialize, but make-u8vector
will, and I was worried the bug was with the latter.
@AlexKnauth see https://github.com/gambit/gambit/commit/fc132b2f9d03b4f0bde9c70cc406ddcc9fbbcbe9
I think we can close this issue, if you are declaring unsafe you should be specifying the initial value yourself.