4 Pointer Functions
procedure
(ptr-equal? cptr1 cptr2) → boolean?
cptr1 : cpointer? cptr2 : cpointer?
If the values are both pointers that are not represented by #f, a byte string, a callback, a pointer based on _fpointer, or a structure with the prop:cpointer property, then the ptr-equal? comparison is the same as using equal?.
procedure
cptr : cpointer? offset : exact-integer? type : ctype? = _byte
The resulting cpointer keeps the base pointer and offset separate. The two pieces are combined at the last minute before any operation on the pointer, such as supplying the pointer to a foreign function. In particular, the pointer and offset are not combined until after all allocation leading up to a foreign-function call; if the called function does not itself call anything that can trigger a garbage collection, it can safely use pointers that are offset into the middle of a GCable object.
procedure
(offset-ptr? cptr) → boolean?
cptr : cpointer?
procedure
(ptr-offset cptr) → exact-integer?
cptr : cpointer?
procedure
(cpointer-gcable? cptr) → boolean?
cptr : cpointer?
For a pointer based on _gcpointer as a result type, cpointer-gcable? will return #t. In the BC implementation of Racket, cpointer-gcable? will return #f for a pointer based on _pointer as a result type. The CS implementation is mostly the same, except that if a pointer is extracted using the _pointer type from memory allocated as 'nonatomic, cpointer-gcable? will report #t for the extracted pointer.
4.1 Pointer Dereferencing
procedure
(set-ptr-offset! cptr offset [ctype]) → void?
cptr : cpointer? offset : exact-integer? ctype : ctype? = _byte
procedure
cptr : cpointer? offset : exact-integer? ctype : ctype? = _byte
procedure
cptr : cpointer? type : ctype? offset : exact-nonnegative-integer? = 0 (ptr-ref cptr type abs-tag offset) → any cptr : cpointer? type : ctype? abs-tag : (one-of/c 'abs) offset : exact-nonnegative-integer? (ptr-set! cptr type val) → void? cptr : cpointer? type : ctype? val : any/c (ptr-set! cptr type offset val) → void? cptr : cpointer? type : ctype? offset : exact-nonnegative-integer? val : any/c (ptr-set! cptr type abs-tag offset val) → void? cptr : cpointer? type : ctype? abs-tag : (one-of/c 'abs) offset : exact-nonnegative-integer? val : any/c
In each case, offset defaults to 0 (which is the
only value that should be used with ffi-obj objects, see
Unexported Primitive Functions). If an offset index is
non-0, the value is read or stored at that location,
considering the pointer as a vector of types —
Beware that the ptr-ref and ptr-set! procedure do not keep any meta-information on how pointers are used. It is the programmer’s responsibility to use this facility only when appropriate. For example, on a little-endian machine:
> (define block (malloc _int 5)) > (ptr-set! block _int 0 196353) > (map (lambda (i) (ptr-ref block _byte i)) '(0 1 2 3)) (1 255 2 0)
In addition, ptr-ref and ptr-set! cannot detect when offsets are beyond an object’s memory bounds; out-of-bounds access can easily lead to a segmentation fault or memory corruption.
procedure
(memmove cptr [ offset] src-cptr [ src-offset] count [ type]) → void? cptr : cpointer? offset : exact-integer? = 0 src-cptr : cpointer? src-offset : exact-integer? = 0 count : exact-nonnegative-integer? type : ctype? = _byte
procedure
(memcpy cptr [ offset] src-cptr [ src-offset] count [ type]) → void? cptr : cpointer? offset : exact-integer? = 0 src-cptr : cpointer? src-offset : exact-integer? = 0 count : exact-nonnegative-integer? type : ctype? = _byte
procedure
cptr : cpointer? offset : exact-integer? = 0 byte : byte? count : exact-nonnegative-integer? type : ctype? = _byte
procedure
(cpointer-tag cptr) → any
cptr : cpointer?
procedure
(set-cpointer-tag! cptr tag) → void?
cptr : cpointer? tag : any/c
4.2 Memory Management
For general information on C-level memory management with Racket, see Inside: Racket C API.
procedure
(malloc bytes-or-type [ type-or-bytes cptr mode fail-mode]) → cpointer?
bytes-or-type :
(or/c (and/c exact-nonnegative-integer? fixnum?) ctype?)
type-or-bytes :
(or/c (and/c exact-nonnegative-integer? fixnum?) ctype?) = absent cptr : cpointer? = absent
mode :
(one-of/c 'raw 'atomic 'nonatomic 'tagged 'atomic-interior 'interior 'stubborn 'uncollectable 'eternal) = absent fail-mode : (one-of/c 'failok) = absent
If a C type bytes-or-type is given, its size is used to determine the block allocation size.
If an integer bytes-or-type is given, it specifies the required size in bytes.
If both bytes-or-type and type-or-bytes are given, then the allocated size is for a vector of values (the multiplication of the size of the C type and the integer).
If a cptr pointer is given, its content is copied to the new block.
A symbol mode argument can be given, which specifies what allocation function to use. It should be one of the following:
'raw —
Allocates memory that is outside the garbage collector’s space and is not traced by the garbage collector (i.e., is treated as holding no pointers to collectable memory). This memory must be freed with free. The initial content of the memory is unspecified. 'atomic —
Allocates memory that can be reclaimed by the garbage collector but is not traced by the garbage collector. The initial content of the memory is unspecified. For the BC Racket implementation, this allocation mode corresponds to scheme_malloc_atomic in the C API.
'nonatomic —
Allocates memory that can be reclaimed by the garbage collector, is treated by the garbage collector as holding only pointers, and is initially filled with zeros. For the BC Racket implementation, this allocation mode corresponds to scheme_malloc in the C API.
For the CS Racket implementation, this mode is of limited use, because a pointer allocated this way cannot be passed to foreign functions that expect a pointer to pointers. The result can only be used with functions like ptr-set! and ptr-ref.
'atomic-interior —
Like 'atomic, but the allocated object will not be moved by the garbage collector as long as the allocated object is retained. For the BC Racket implementation, a reference can point to the interior of the object, instead of its starting address. This allocation mode corresponds to scheme_malloc_atomic_allow_interior in the C API.
'nonatomic-interior —
Like 'nonatomic, but the allocated object will not be moved by the garbage collector as long as the allocated object is retained. This mode is supported only for the BC Racket implementation, and it corresponds to scheme_malloc_allow_interior in the C API.
'tagged —
Allocates memory that must start with a short value that is registered as a tag with the garbage collector. This mode is supported only for the BC Racket implementation, and it corresponds to scheme_malloc_tagged in the C API.
'stubborn —
Like 'nonatomic, but supports a hint to the GC via end-stubborn-change after all changes to the object have been made. This mode is supported only for the BC Racket implementation, and it corresponds to scheme_malloc_stubborn in the C API.
'eternal —
Like 'raw, except the allocated memory cannot be freed. This mode is supported only for the CGC Racket variant, and it corresponds to scheme_malloc_uncollectable in the C API.
'uncollectable —
Allocates memory that is never collected, cannot be freed, and potentially contains pointers to collectable memory. This mode is supported only for the CGC Racket variant, and it corresponds to scheme_malloc_uncollectable in the C API.
If an additional 'failok flag is given, then some effort may be made to detect an allocation failure and raise exn:fail:out-of-memory instead of crashing.
If no mode is specified, then 'nonatomic allocation is used when the type is a _gcpointer- or _scheme-based type, and 'atomic allocation is used otherwise.
Changed in version 6.4.0.10 of package base: Added the 'tagged allocation mode.
Memory allocated with malloc and modes other than 'raw must not be freed, since those modes allocate memory that is managed by the garbage collector.
procedure
(end-stubborn-change cptr) → void?
cptr : cpointer?
procedure
v : any/c
procedure
(free-immobile-cell cptr) → void?
cptr : cpointer?
The finalizer is invoked in a thread that is in charge of triggering will executors for register-finalizer. The given finalizer procedure should generally not rely on the environment of the triggering thread, and it must not use any parameters or call any parameter functions, except that relying on a default logger and/or calling current-logger is allowed.
Finalizers are mostly intended to be used with cpointer objects (for
freeing unused memory that is not under GC control), but it can be
used with any Racket object—
As an example for register-finalizer, suppose that you’re dealing with a foreign function that returns a C string that you should free. Here is an attempt at creating a suitable type:
(define _sixteen-bytes/free (make-ctype _pointer #f ; a Racket bytes can be used as a pointer (lambda (x) (let ([b (make-sized-byte-string x 16)]) (register-finalizer x free) b))))
The above code is wrong: the finalizer is registered for x, which is no longer needed after the byte string is created. Changing the example to register the finalizer for b corrects the problem, but then free is invoked b it instead of on x. In the process of fixing this problem, we might be careful and log a message for debugging:
(define _sixteen-bytes/free (make-ctype _pointer #f ; a Racket bytes can be used as a pointer (lambda (x) (let ([b (make-sized-byte-string x 16)]) (register-finalizer b (lambda (ignored) (log-debug (format "Releasing ~s\n" b)) (free x))) b))))
Now, we never see any logged event. The problem is that the finalizer is a closure that keeps a reference to b. Instead of referencing the value that is finalized, use the input argument to the finalizer; simply changing ignored to b above solves the problem. (Removing the debugging message also avoids the problem, since the finalization procedure would then not close over b.)
procedure
(make-late-weak-box v) → weak-box?
v : any/c
procedure
(make-late-weak-hasheq v) → (and/c hash? hash-eq? hash-weak?)
v : any/c
procedure
(make-sized-byte-string cptr length) → bytes?
cptr : cpointer? length : exact-nonnegative-integer?
Beware that the representation of a Racket byte string normally
requires a nul terminator at the end of the byte string (after
length bytes), but some functions work with a byte-string
representation that has no such terminator—
If cptr is an offset pointer created by ptr-add, the offset is immediately added to the pointer. Thus, this function cannot be used with ptr-add to create a substring of a Racket byte string, because the offset pointer would be to the middle of a collectable object (which is not allowed).
procedure
(void/reference-sink v ...) → void?
v : any/c
Added in version 6.10.1.2 of package base.
4.3 Pointer Structure Property
The prop:cpointer property allows a structure instance to be used transparently as a C pointer value, or it allows a C pointer value to be transparently wrapped by a structure that may have additional values or properties.