56 lines
2.3 KiB
Plaintext
56 lines
2.3 KiB
Plaintext
;;;; Two rendered numbers, held at once.
|
|
;;;;
|
|
;;;; i64->bytes and its two siblings render into a buffer and answer a slice
|
|
;;;; over it. That buffer used to be one file-static in the runtime, shared by
|
|
;;;; every call in the process, so the program below printed "22 22": the
|
|
;;;; second conversion overwrote the first, and the first slice — still a
|
|
;;;; perfectly valid pointer into a perfectly live buffer — was read after it.
|
|
;;;; No crash, no diagnostic, and nothing for a sanitizer to catch, because
|
|
;;;; every byte read was inside an object that was alive. The wrong bytes.
|
|
;;;;
|
|
;;;; The conversion's bytes are now copied into the temp allocator, so a
|
|
;;;; result outlives the frame that made it: the last two cases return one from
|
|
;;;; a function and push them into a Vec that outlives the loop that made them.
|
|
(defn numstr [n i64] str
|
|
(str (i64->bytes n)))
|
|
|
|
(defn main [] i32
|
|
;; Two i64 conversions alive at the same time.
|
|
(let [a (str (i64->bytes 11))
|
|
b (str (i64->bytes 22))]
|
|
(print a) (print " ") (println b)) ; 11 22
|
|
|
|
;; Three, and read in the order they were made rather than in reverse, so a
|
|
;; version that rotated among two buffers would still be caught.
|
|
(let [a (str (i64->bytes 1))
|
|
b (str (i64->bytes 2))
|
|
c (str (i64->bytes 3))]
|
|
(print a) (print b) (println c)) ; 123
|
|
|
|
;; Across the two shims: the f64's text is made first and read last.
|
|
(let [x (str (f64->bytes 2.5))
|
|
n (str (i64->bytes 7))]
|
|
(print x) (print " ") (println n)) ; 2.5 7
|
|
|
|
;; Inside a loop, one conversion per turn. Printed on one line so the
|
|
;; loop's shape is visible in the output.
|
|
(dotimes [i 4]
|
|
(let [s (str (i64->bytes (i64 (* i 11))))]
|
|
(print s) (print " ")))
|
|
(println "") ; 0 11 22 33
|
|
|
|
;; Returned from the function that made it. With the text in that
|
|
;; function's frame, the second call wrote over the first.
|
|
(let [a (numstr 11)
|
|
b (numstr 22)]
|
|
(print a) (print " ") (println b)) ; 11 22
|
|
|
|
;; Pushed, and read after the loop.
|
|
(let [v (vec-new [u8])]
|
|
(dotimes [i 3]
|
|
(push v (f64->bytes (+ (f64 i) 0.5))))
|
|
(dotimes [i 3]
|
|
(print (str (at v i))) (print " "))
|
|
(println "")) ; 0.5 1.5 2.5
|
|
0)
|