Is storing data and a mutable pointer to that data in a struct safe?












1














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.










share|improve this question
























  • 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
















1














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.










share|improve this question
























  • 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














1












1








1







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.










share|improve this question















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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 to UnsafeCell. 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






  • 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
















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












1 Answer
1






active

oldest

votes


















3














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:




  1. The Wrapper is never moved.

  2. 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()) }
}
}





share|improve this answer























  • 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











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
});


}
});














draft saved

draft discarded


















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









3














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:




  1. The Wrapper is never moved.

  2. 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()) }
}
}





share|improve this answer























  • 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
















3














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:




  1. The Wrapper is never moved.

  2. 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()) }
}
}





share|improve this answer























  • 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














3












3








3






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:




  1. The Wrapper is never moved.

  2. 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()) }
}
}





share|improve this answer














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:




  1. The Wrapper is never moved.

  2. 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()) }
}
}






share|improve this answer














share|improve this answer



share|improve this answer








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


















  • 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


















draft saved

draft discarded




















































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.




draft saved


draft discarded














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





















































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







Popular posts from this blog

Bressuire

Vorschmack

Quarantine