Is changing an immutable variable by pointer a UB?

I have a static variable of type Option, I want to initialize it once, but I don't want to make it mutable otherwise I will need to synchronize access to it, which is unnecessary because it will not be changed afterwards.
For this purpose I initialize it once using a pointer. Is this a UB?

1 Like

And what about non-static variables, too?

Mutating memory through a pointer that does not have write access is always UB, doesn't matter if it points to a static or non-static memory. What you want can be done using just safe code with std::sync::OnceLock/std::sync::LazyLock

4 Likes

Unfortunately, I am in a no_std environment and cannot use it.

Pointer itself has write access, I didn't quite understand you.

If you have a non-mut X and a pointer to X, the pointer never can have write permission.
Using such a pointer to write to X is always UB.
So, you should change your code.

2 Likes

Initializing statics once and then just reading them is the primary use case of std::sync::LazyLock.

1 Like

In core there's LazyCell which you can use instead of LazyLock. You just have to access it via a function call. that's not the right type

lazy_static is no_std and does not depend on alloc as far as I can tell.

3 Likes

Would static_cell crate suit your needs? We use it in our embedded code and it's great

4 Likes

Here's a no_std Lazy implementation Lazy in spin::lazy - Rust

2 Likes

you can use once_cell::sync::OnceCell or once_cell::sync::Lazy on #![no_std] with the critical_section feature enabled, which should work on many embedded platforms. If you can use alloc, you can also use once_cell::race::OnceBox which doesn't need critical_section assuming you have atomics.

2 Likes