Is storing data and a mutable pointer to that data in a struct safe?
Let's consider a Rust wrapper library around a C library. This C library defines a struct and uses it as a mutable pointer throughout it's API.
The Rust wrapper defines the following struct with ptr
pointing at data
.
struct Wrapper
data: struct_from_c_t,
ptr: *mut struct_from_c_t,
If all uses of this pointer are made within the Wrapper
struct's lifetime, what other potential issues can I run into when using this pointer in unsafe code ?
Is dereference and use of this pointer always safe in this construct?
For detailed context, the goal is to be able to call FFI functions using this pointer from functions borrowing Wrapper
non-mutably.
rust ffi unsafe
add a comment |
Let's consider a Rust wrapper library around a C library. This C library defines a struct and uses it as a mutable pointer throughout it's API.
The Rust wrapper defines the following struct with ptr
pointing at data
.
struct Wrapper
data: struct_from_c_t,
ptr: *mut struct_from_c_t,
If all uses of this pointer are made within the Wrapper
struct's lifetime, what other potential issues can I run into when using this pointer in unsafe code ?
Is dereference and use of this pointer always safe in this construct?
For detailed context, the goal is to be able to call FFI functions using this pointer from functions borrowing Wrapper
non-mutably.
rust ffi unsafe
As far as I know what you are doing is undefined behavoir. You have to use an Unsafecell to achieve it. But I'm not very experienced with FFIs so this is not an answer ;)
– hellow
Nov 12 '18 at 14:12
1
Thanks, not taking this as an answer but I will definitely take a look at UnsafeCell to see if I can use it to make a safe wrapper.
– Sisyphe
Nov 12 '18 at 14:15
If you want to know anything about FFI, read the rustonomicon
– hellow
Nov 12 '18 at 14:21
2
I see no reason to go toUnsafeCell
. That's used for building your own abstractions, but existing abstractions are sufficient.
– Shepmaster
Nov 12 '18 at 14:24
add a comment |
Let's consider a Rust wrapper library around a C library. This C library defines a struct and uses it as a mutable pointer throughout it's API.
The Rust wrapper defines the following struct with ptr
pointing at data
.
struct Wrapper
data: struct_from_c_t,
ptr: *mut struct_from_c_t,
If all uses of this pointer are made within the Wrapper
struct's lifetime, what other potential issues can I run into when using this pointer in unsafe code ?
Is dereference and use of this pointer always safe in this construct?
For detailed context, the goal is to be able to call FFI functions using this pointer from functions borrowing Wrapper
non-mutably.
rust ffi unsafe
Let's consider a Rust wrapper library around a C library. This C library defines a struct and uses it as a mutable pointer throughout it's API.
The Rust wrapper defines the following struct with ptr
pointing at data
.
struct Wrapper
data: struct_from_c_t,
ptr: *mut struct_from_c_t,
If all uses of this pointer are made within the Wrapper
struct's lifetime, what other potential issues can I run into when using this pointer in unsafe code ?
Is dereference and use of this pointer always safe in this construct?
For detailed context, the goal is to be able to call FFI functions using this pointer from functions borrowing Wrapper
non-mutably.
rust ffi unsafe
rust ffi unsafe
edited Nov 12 '18 at 14:22
Shepmaster
150k13291429
150k13291429
asked Nov 12 '18 at 14:06
SisypheSisyphe
385
385
As far as I know what you are doing is undefined behavoir. You have to use an Unsafecell to achieve it. But I'm not very experienced with FFIs so this is not an answer ;)
– hellow
Nov 12 '18 at 14:12
1
Thanks, not taking this as an answer but I will definitely take a look at UnsafeCell to see if I can use it to make a safe wrapper.
– Sisyphe
Nov 12 '18 at 14:15
If you want to know anything about FFI, read the rustonomicon
– hellow
Nov 12 '18 at 14:21
2
I see no reason to go toUnsafeCell
. That's used for building your own abstractions, but existing abstractions are sufficient.
– Shepmaster
Nov 12 '18 at 14:24
add a comment |
As far as I know what you are doing is undefined behavoir. You have to use an Unsafecell to achieve it. But I'm not very experienced with FFIs so this is not an answer ;)
– hellow
Nov 12 '18 at 14:12
1
Thanks, not taking this as an answer but I will definitely take a look at UnsafeCell to see if I can use it to make a safe wrapper.
– Sisyphe
Nov 12 '18 at 14:15
If you want to know anything about FFI, read the rustonomicon
– hellow
Nov 12 '18 at 14:21
2
I see no reason to go toUnsafeCell
. That's used for building your own abstractions, but existing abstractions are sufficient.
– Shepmaster
Nov 12 '18 at 14:24
As far as I know what you are doing is undefined behavoir. You have to use an Unsafecell to achieve it. But I'm not very experienced with FFIs so this is not an answer ;)
– hellow
Nov 12 '18 at 14:12
As far as I know what you are doing is undefined behavoir. You have to use an Unsafecell to achieve it. But I'm not very experienced with FFIs so this is not an answer ;)
– hellow
Nov 12 '18 at 14:12
1
1
Thanks, not taking this as an answer but I will definitely take a look at UnsafeCell to see if I can use it to make a safe wrapper.
– Sisyphe
Nov 12 '18 at 14:15
Thanks, not taking this as an answer but I will definitely take a look at UnsafeCell to see if I can use it to make a safe wrapper.
– Sisyphe
Nov 12 '18 at 14:15
If you want to know anything about FFI, read the rustonomicon
– hellow
Nov 12 '18 at 14:21
If you want to know anything about FFI, read the rustonomicon
– hellow
Nov 12 '18 at 14:21
2
2
I see no reason to go to
UnsafeCell
. That's used for building your own abstractions, but existing abstractions are sufficient.– Shepmaster
Nov 12 '18 at 14:24
I see no reason to go to
UnsafeCell
. That's used for building your own abstractions, but existing abstractions are sufficient.– Shepmaster
Nov 12 '18 at 14:24
add a comment |
1 Answer
1
active
oldest
votes
This is generally a bad idea and it can go wrong very easily.
First, go read Why can't I store a value and a reference to that value in the same struct? for an in-depth explanation about why safe Rust prevents this construct at compile time.
TL;DR, if you ever move the Wrapper
struct, the pointer will be invalid. Dereferencing it will cause undefined behavior (a bad thing).
If you can ensure that either of:
- The
Wrapper
is never moved. - The
ptr
is updated every time you move the struct.
Then the pointer will be valid and safe to dereference (assuming all the other caveats about unsafe code are upheld).
What's worse is that there's no reason to keep the pointer in the first place; you can take a reference to a value and convert it into a pointer whenever you need:
extern "C"
fn ffi_fn(data: *mut struct_from_c_t);
struct Wrapper
data: struct_from_c_t,
impl Wrapper
fn do_thing(&mut self)
unsafe ffi_fn(&mut self.data)
from functions borrowing
Wrapper
non-mutably
Without context, this seems like a dubious decision, but Rust has tools for interior mutability:
use std::cell::RefCell;
struct Wrapper
data: RefCell<struct_from_c_t>,
impl Wrapper
fn do_thing(&self)
unsafe ffi_fn(&mut *self.data.borrow_mut())
The struct is still mutably borrowed but I think it's a mistype (I can't edit your pose since stackoverflow request at least 6 characters modification). The RefCell example seems fine. Is there something to worry about with unsafe usage of RefCell ? (the doc doesn't mention anything)
– Sisyphe
Nov 12 '18 at 14:44
1
No,RefCell
will panic and stop your program if you ever attempt to get two aliased mutable references, ensuring your program's memory safety.
– Shepmaster
Nov 12 '18 at 14:48
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53263849%2fis-storing-data-and-a-mutable-pointer-to-that-data-in-a-struct-safe%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
This is generally a bad idea and it can go wrong very easily.
First, go read Why can't I store a value and a reference to that value in the same struct? for an in-depth explanation about why safe Rust prevents this construct at compile time.
TL;DR, if you ever move the Wrapper
struct, the pointer will be invalid. Dereferencing it will cause undefined behavior (a bad thing).
If you can ensure that either of:
- The
Wrapper
is never moved. - The
ptr
is updated every time you move the struct.
Then the pointer will be valid and safe to dereference (assuming all the other caveats about unsafe code are upheld).
What's worse is that there's no reason to keep the pointer in the first place; you can take a reference to a value and convert it into a pointer whenever you need:
extern "C"
fn ffi_fn(data: *mut struct_from_c_t);
struct Wrapper
data: struct_from_c_t,
impl Wrapper
fn do_thing(&mut self)
unsafe ffi_fn(&mut self.data)
from functions borrowing
Wrapper
non-mutably
Without context, this seems like a dubious decision, but Rust has tools for interior mutability:
use std::cell::RefCell;
struct Wrapper
data: RefCell<struct_from_c_t>,
impl Wrapper
fn do_thing(&self)
unsafe ffi_fn(&mut *self.data.borrow_mut())
The struct is still mutably borrowed but I think it's a mistype (I can't edit your pose since stackoverflow request at least 6 characters modification). The RefCell example seems fine. Is there something to worry about with unsafe usage of RefCell ? (the doc doesn't mention anything)
– Sisyphe
Nov 12 '18 at 14:44
1
No,RefCell
will panic and stop your program if you ever attempt to get two aliased mutable references, ensuring your program's memory safety.
– Shepmaster
Nov 12 '18 at 14:48
add a comment |
This is generally a bad idea and it can go wrong very easily.
First, go read Why can't I store a value and a reference to that value in the same struct? for an in-depth explanation about why safe Rust prevents this construct at compile time.
TL;DR, if you ever move the Wrapper
struct, the pointer will be invalid. Dereferencing it will cause undefined behavior (a bad thing).
If you can ensure that either of:
- The
Wrapper
is never moved. - The
ptr
is updated every time you move the struct.
Then the pointer will be valid and safe to dereference (assuming all the other caveats about unsafe code are upheld).
What's worse is that there's no reason to keep the pointer in the first place; you can take a reference to a value and convert it into a pointer whenever you need:
extern "C"
fn ffi_fn(data: *mut struct_from_c_t);
struct Wrapper
data: struct_from_c_t,
impl Wrapper
fn do_thing(&mut self)
unsafe ffi_fn(&mut self.data)
from functions borrowing
Wrapper
non-mutably
Without context, this seems like a dubious decision, but Rust has tools for interior mutability:
use std::cell::RefCell;
struct Wrapper
data: RefCell<struct_from_c_t>,
impl Wrapper
fn do_thing(&self)
unsafe ffi_fn(&mut *self.data.borrow_mut())
The struct is still mutably borrowed but I think it's a mistype (I can't edit your pose since stackoverflow request at least 6 characters modification). The RefCell example seems fine. Is there something to worry about with unsafe usage of RefCell ? (the doc doesn't mention anything)
– Sisyphe
Nov 12 '18 at 14:44
1
No,RefCell
will panic and stop your program if you ever attempt to get two aliased mutable references, ensuring your program's memory safety.
– Shepmaster
Nov 12 '18 at 14:48
add a comment |
This is generally a bad idea and it can go wrong very easily.
First, go read Why can't I store a value and a reference to that value in the same struct? for an in-depth explanation about why safe Rust prevents this construct at compile time.
TL;DR, if you ever move the Wrapper
struct, the pointer will be invalid. Dereferencing it will cause undefined behavior (a bad thing).
If you can ensure that either of:
- The
Wrapper
is never moved. - The
ptr
is updated every time you move the struct.
Then the pointer will be valid and safe to dereference (assuming all the other caveats about unsafe code are upheld).
What's worse is that there's no reason to keep the pointer in the first place; you can take a reference to a value and convert it into a pointer whenever you need:
extern "C"
fn ffi_fn(data: *mut struct_from_c_t);
struct Wrapper
data: struct_from_c_t,
impl Wrapper
fn do_thing(&mut self)
unsafe ffi_fn(&mut self.data)
from functions borrowing
Wrapper
non-mutably
Without context, this seems like a dubious decision, but Rust has tools for interior mutability:
use std::cell::RefCell;
struct Wrapper
data: RefCell<struct_from_c_t>,
impl Wrapper
fn do_thing(&self)
unsafe ffi_fn(&mut *self.data.borrow_mut())
This is generally a bad idea and it can go wrong very easily.
First, go read Why can't I store a value and a reference to that value in the same struct? for an in-depth explanation about why safe Rust prevents this construct at compile time.
TL;DR, if you ever move the Wrapper
struct, the pointer will be invalid. Dereferencing it will cause undefined behavior (a bad thing).
If you can ensure that either of:
- The
Wrapper
is never moved. - The
ptr
is updated every time you move the struct.
Then the pointer will be valid and safe to dereference (assuming all the other caveats about unsafe code are upheld).
What's worse is that there's no reason to keep the pointer in the first place; you can take a reference to a value and convert it into a pointer whenever you need:
extern "C"
fn ffi_fn(data: *mut struct_from_c_t);
struct Wrapper
data: struct_from_c_t,
impl Wrapper
fn do_thing(&mut self)
unsafe ffi_fn(&mut self.data)
from functions borrowing
Wrapper
non-mutably
Without context, this seems like a dubious decision, but Rust has tools for interior mutability:
use std::cell::RefCell;
struct Wrapper
data: RefCell<struct_from_c_t>,
impl Wrapper
fn do_thing(&self)
unsafe ffi_fn(&mut *self.data.borrow_mut())
edited Nov 12 '18 at 14:45
answered Nov 12 '18 at 14:18
ShepmasterShepmaster
150k13291429
150k13291429
The struct is still mutably borrowed but I think it's a mistype (I can't edit your pose since stackoverflow request at least 6 characters modification). The RefCell example seems fine. Is there something to worry about with unsafe usage of RefCell ? (the doc doesn't mention anything)
– Sisyphe
Nov 12 '18 at 14:44
1
No,RefCell
will panic and stop your program if you ever attempt to get two aliased mutable references, ensuring your program's memory safety.
– Shepmaster
Nov 12 '18 at 14:48
add a comment |
The struct is still mutably borrowed but I think it's a mistype (I can't edit your pose since stackoverflow request at least 6 characters modification). The RefCell example seems fine. Is there something to worry about with unsafe usage of RefCell ? (the doc doesn't mention anything)
– Sisyphe
Nov 12 '18 at 14:44
1
No,RefCell
will panic and stop your program if you ever attempt to get two aliased mutable references, ensuring your program's memory safety.
– Shepmaster
Nov 12 '18 at 14:48
The struct is still mutably borrowed but I think it's a mistype (I can't edit your pose since stackoverflow request at least 6 characters modification). The RefCell example seems fine. Is there something to worry about with unsafe usage of RefCell ? (the doc doesn't mention anything)
– Sisyphe
Nov 12 '18 at 14:44
The struct is still mutably borrowed but I think it's a mistype (I can't edit your pose since stackoverflow request at least 6 characters modification). The RefCell example seems fine. Is there something to worry about with unsafe usage of RefCell ? (the doc doesn't mention anything)
– Sisyphe
Nov 12 '18 at 14:44
1
1
No,
RefCell
will panic and stop your program if you ever attempt to get two aliased mutable references, ensuring your program's memory safety.– Shepmaster
Nov 12 '18 at 14:48
No,
RefCell
will panic and stop your program if you ever attempt to get two aliased mutable references, ensuring your program's memory safety.– Shepmaster
Nov 12 '18 at 14:48
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53263849%2fis-storing-data-and-a-mutable-pointer-to-that-data-in-a-struct-safe%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
As far as I know what you are doing is undefined behavoir. You have to use an Unsafecell to achieve it. But I'm not very experienced with FFIs so this is not an answer ;)
– hellow
Nov 12 '18 at 14:12
1
Thanks, not taking this as an answer but I will definitely take a look at UnsafeCell to see if I can use it to make a safe wrapper.
– Sisyphe
Nov 12 '18 at 14:15
If you want to know anything about FFI, read the rustonomicon
– hellow
Nov 12 '18 at 14:21
2
I see no reason to go to
UnsafeCell
. That's used for building your own abstractions, but existing abstractions are sufficient.– Shepmaster
Nov 12 '18 at 14:24