-
Notifications
You must be signed in to change notification settings - Fork 95
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Ctypes_memory.keep_alive
function
#777
base: master
Are you sure you want to change the base?
Conversation
Expose this function as Ctypes.keep_alive, and add documentation to the Ctypes.mli for it. In addition, remove the old `use_value` completely: from ctypes_roots.c, from cstubs_memory_stubs.ml. Add `Cstubs_internal.keep_alive` and change code-gen to use this instead of old `use_value`.
Related to: #571 |
@@ -198,6 +198,24 @@ val allocate_n : ?finalise:('a ptr -> unit) -> 'a typ -> count:int -> 'a ptr | |||
memory is allocated with libc's [calloc] and is guaranteed to be | |||
zero-filled. *) | |||
|
|||
val keep_alive : 'a -> unit | |||
(** Inserting [keep_alive x;] in a sequence of expressions ensures that |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(** Inserting [keep_alive x;] in a sequence of expressions ensures that | |
(** Inserting [keep_alive x] in a sequence of expressions ensures that |
@@ -198,6 +198,24 @@ val allocate_n : ?finalise:('a ptr -> unit) -> 'a typ -> count:int -> 'a ptr | |||
memory is allocated with libc's [calloc] and is guaranteed to be | |||
zero-filled. *) | |||
|
|||
val keep_alive : 'a -> unit | |||
(** Inserting [keep_alive x;] in a sequence of expressions ensures that | |||
the garbage collector will not collect [x] until after that [keep_alive] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the garbage collector will not collect [x] until after that [keep_alive] | |
the garbage collector will not collect [x] until [keep_alive] |
let strchr = Foreign.foreign "strchr" (ptr char @-> char @-> returning (ptr char)) in | ||
let p = CArray.of_string "abc" in | ||
let q = strchr (CArray.start p) 'a' in | ||
let () = Gc.compact () in | ||
let () = Printf.printf "%c\n" !@q in | ||
keep_alive p; | ||
]} | ||
Without the [keep_alive p] at the bottom, [p] could be collected during the | ||
[Gc.compact ()] call, which would make [q] an invalid pointer into the | ||
now-collected [p], leading to undefined behavior. *) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a nice example, but I think it would be even stronger without the call to Gc.compact
, because most programs don't call Gc
functions.
let q = strchr (CArray.start p) 'a' in | ||
let () = Gc.compact () in | ||
let () = Printf.printf "%c\n" !@q in | ||
keep_alive p; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
keep_alive p; | |
keep_alive p |
(* To avoid a dependence on Ctypes_memory, we redefine keep_alive here. *) | ||
let keep_alive x = ignore (Sys.opaque_identity x) in | ||
Gc.finalise (fun _ -> keep_alive src) ba; ba |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(* To avoid a dependence on Ctypes_memory, we redefine keep_alive here. *) | |
let keep_alive x = ignore (Sys.opaque_identity x) in | |
Gc.finalise (fun _ -> keep_alive src) ba; ba | |
Gc.finalise (fun _ -> ignore (Sys.opaque_identity src)) ba; ba |
@@ -1,6 +1,6 @@ | |||
(lang dune 2.9) | |||
(name ctypes) | |||
(version 0.22.0) | |||
(version 0.23.0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's no need to change the version
let () = Printf.printf "%c\n" !@q in | ||
keep_alive p; | ||
]} | ||
Without the [keep_alive p] at the bottom, [p] could be collected during the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Without the [keep_alive p] at the bottom, [p] could be collected during the | |
Without [keep_alive p], [p] could be collected during the |
keep_alive p; | ||
]} | ||
Without the [keep_alive p] at the bottom, [p] could be collected during the | ||
[Gc.compact ()] call, which would make [q] an invalid pointer into the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Gc.compact ()] call, which would make [q] an invalid pointer into the | |
[Gc.compact ()] call, making [q] an invalid pointer into the |
Expose this function as Ctypes.keep_alive, and add documentation to the Ctypes.mli for it. In addition, remove the old
use_value
completely: from ctypes_roots.c, from cstubs_memory_stubs.ml.Add
Cstubs_internal.keep_alive
and change code-gen to use this instead of olduse_value
.