0

I just wanted to declare a pointer to a struct in a crate shared by several components of my project but using the same process. I mean the aim is to get it initialized only once.

type Box = [u64; 64];
pub static mut mmaped: &mut Box;

which at compile time generated this error.

free static item without body

Where mmaped is later assigned a value in the following way only one time from the top crate and it s value used from the multiple crates it depends on.

mmaped = unsafe { std::mem::transmute(addr) };

So how do I provide a definition of mmaped without having to mmap it more than one time?

This question isn't a duplicate of How do I create a global, mutable singleton?, as it doesn't talk about exporting the singleton outside the crate and I'm getting a compiler error specifically for doing it.

E_net4
  • 27,810
  • 13
  • 101
  • 139
user2284570
  • 2,891
  • 3
  • 26
  • 74
  • @pretzelhammer I edited my question, but this doesn t appears to apply exactly to my specific case as it doesn t explain how to get it exported outside the crate. – user2284570 Dec 14 '20 at 16:48
  • Please [edit] your question to contain a [mre] that either (1) demonstrates the error you're currently getting or (2) compiles but does not have the desired behavior (and explain what the desired behavior is). In particular, it's not clear what you mean by "without having to mmap it more than one time". `mmap` is a [specific thing](https://en.wikipedia.org/wiki/Mmap); if you're not referring to that you should probably try to find different words to describe the behavior you want. – trent Dec 14 '20 at 17:22
  • @trentcl `type Box = [u64; 64]; pub static mut mmaped: &mut Box;` is the minimal example trigerring the error. – user2284570 Dec 14 '20 at 17:24
  • @trentcl https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=eb9a09e43bf6495eb950fcea1a967ae6 – user2284570 Dec 14 '20 at 17:33
  • Um... ok... I must be missing something. You can't declare an uninitialized `static`, that's what the error is telling you. It's not valid code because it doesn't *mean* anything. So... what do you want it to mean? Maybe you want to create a static `Option`? (``pub static mut MMAPPED: Option<&mut [u64; 64]> = None;``) – trent Dec 14 '20 at 17:34
  • @trentcl but then, it s value will be reinitilized to `None` each time my crate is loaded by a new thread? – user2284570 Dec 14 '20 at 17:38
  • 1
    No, spawning a new thread does not re-initialize static variables, which are shared between threads. If you wanted that behavior you would need to use `thread_local`. (But realistically you probably want to use `lazy_static` instead of `static mut`, which is prone to UB if you are not extremely careful) – trent Dec 14 '20 at 17:40
  • @trentcl this doesn t seems to be the case as show by this playground https://stackoverflow.com/a/65270812/2284570. – user2284570 Dec 14 '20 at 17:42
  • 1
    There's no `static` in that example, just two local variables initialized separately. – trent Dec 14 '20 at 17:44
  • @trentcl I m meaning this since the thread will load the crate one more time. – user2284570 Dec 14 '20 at 18:13
  • 1
    @user2284570 I realized that [your question](https://stackoverflow.com/questions/65270748/when-implementing-the-default-trait-for-a-struct-and-intializing-its-members-us/65294420#65294420) was misunderstood, so I added an answer. – Ibraheem Ahmed Dec 14 '20 at 18:32
  • 2
    _"it doesn't talk about exporting the singleton outside the crate"_ It is unclear what stopped you from making the singleton public (`pub`) for other crates to access. Should that be clarified, it would eventually stop being a duplicate then. – E_net4 Apr 28 '23 at 11:11

1 Answers1

-1

The Rust compiler (2018) is not able to generate a valid static item from your code because it lacks a body. You are attempting to declare a static variable mmaped but not actually initializing it with any value. All static variables must be initialized with a value at compile time.

std::mem::MaybeUninit seems to be a perfect solution for this use-case. Initialize it with an 'uninitialized' value. Later update it with your actual value. Since, it is static, it won't allow further initialization.

use std::mem::MaybeUninit;
type Box = [u64; 64];
pub static mut mmaped: MaybeUninit<Box> = MaybeUninit::uninit();

// later
unsafe {
    mmaped = MaybeUninit::new([0; 64]);
}

Just make sure you don't access the mmaped before your actual initialization.

Jishan Shaikh
  • 1,572
  • 2
  • 13
  • 31
  • This seems much too risky and with little benefit over just exposing an `Option<_>` with synchronization mechanisms. – E_net4 Apr 28 '23 at 11:11