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 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 at 14:15
If you want to know anything about FFI, read the rustonomicon
– hellow
Nov 12 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 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 at 14:22
Shepmaster
147k11282415
147k11282415
asked Nov 12 at 14:06
Sisyphe
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 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 at 14:15
If you want to know anything about FFI, read the rustonomicon
– hellow
Nov 12 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 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 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 at 14:15
If you want to know anything about FFI, read the rustonomicon
– hellow
Nov 12 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 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 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 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 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 at 14:15
If you want to know anything about FFI, read the rustonomicon
– hellow
Nov 12 at 14:21
If you want to know anything about FFI, read the rustonomicon
– hellow
Nov 12 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 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 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 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 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 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 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 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 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 at 14:45
answered Nov 12 at 14:18
Shepmaster
147k11282415
147k11282415
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 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 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 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 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 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 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 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 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.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- 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 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 at 14:15
If you want to know anything about FFI, read the rustonomicon
– hellow
Nov 12 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 at 14:24