#'?' operator in Lazy::new closure?
20 messages · Page 1 of 1 (latest)
i think it depends on what an error means
if this thing ever returns an error is that something that might be expected or a bug in your program?
Something I expect I guess.
you could just have a Lazy holding a Result<T, MyErr>
Then you'd need to handle the result everywhere you use the lazy
Hmm okay I see. that makes it rather inconvenient :D So it's probably best to stick with .unwrap() / .expect() within the lazy block as it is an error that can only happen upon initialization and not every time I use the lazy
thanks!
Can you expand on your use case?
i'm not convinced there isn't a better way
what about using OnceCell and initializing it in main? Or even better, just dont use globals?
It's a BTreeMap of addresses found within a specified memory region:
pub static ADDRESSES: Lazy<Result<BTreeMap<&str, u64>>> = Lazy::new(|| -> Result<BTreeMap<&str, u64>> {
let addresses = PatternScanner::new(memory::get_memory_segments())
.with_pattern(
Section::Name(".text".into()),
Pattern::from_str("56 8B F1 83 7E 60 00 74 44")?,
)
.with_pattern(
Section::Name(".data".into()),
Pattern::from_str("75 1B A1 ? ? ? ? 89 45 F8")?,
)
.scan()?;
let mut iter = addresses.iter();
Ok(BTreeMap::from([
("Foo", *iter.next().unwrap()),
("Bar", *iter.next().unwrap()),
]))
});
The idea is to perform the scanning only once and fill up a BTreeMap of data/code segments mapped to their found addresses. Unfortunately I can't avoid globals because I'm within a DLL which means that after the DLL initialization routine has returned, the data on the stack would be gone. I need some global state for that.
you'll have to refresh my memory a bit, iirc you can have some sort of "main" function that is executed when you load it? This " initialization routine"?
Yes exactly:
#[no_mangle]
#[allow(non_snake_case)]
unsafe extern "system" fn DllMain(_hinst_dll: HINSTANCE, fdw_reason: DWORD, _reserved: LPVOID) -> BOOL {
match fdw_reason {
DLL_PROCESS_ATTACH => {
// register panic handler
panic::set_hook(Box::new(|info| {
println!("{info}");
error!("{info}");
}));
// returns here which means I need the global state
}
_ => (),
}
TRUE
}
what about ```rust
pub static ADDRESSES: OnceCell<???> = OnceCell::new();
#[no_mangle]
pub fn dll_main(???) -> ??? {
let addresses = ...;
match addresses{
Ok(value) => ADDRESSES.set(value),
Err(e) => return false
}
}```
ah i see, yeah that could work. this way I can return early in case the initialization fails
and everytime i access ADDRESSES, I wouldn't need to unwrap anymore
right
that clarifies it, thanks for your time :)
oh before you leave. you mind taking a look at this if you still got time? https://discord.com/channels/273534239310479360/1068625946954956821 It seems like nobody can help me with this design decision