Win32 (Module32First function) weird behavior

I'm trying to list all modules that Process has loaded with winapi::um::tlhelp32::CreateToolhelp32Snapshot function from winapi create and I have encountered weird bug in my code where if I remove my println! calls it would cause the Module32First function to return FALSE instead of returning TRUE if I keep them in my code.

Code example:

Basically I'm calling FindWindowA to find HWND and then getting process_id and handle with GetWindowThreadProcessId & OpenProcess functions, after that I call my own take_snapshot function with handle and process_id which executes CreateToolhelp32Snapshot and Module32First functions from winapi. If I remove my println! calls from take_snapshot function, Module32First always fails but if I print out something to console it succeeds.


module_entry.assume_init().dwSize = size_of::<MODULEENTRY32>() as u32;


module_entry.assume_init_mut().dwSize = size_of::<MODULEENTRY32>() as u32;

fixed my problem, but I'm still not sure how did my println! calls change the outcome of function.

You are calling assume_init immediately after creating a MaybeUninit. This is always UB. The outcome of the program changing based on unrelated calls is a symptom of UB. Changing to assume_init_mut does not change that it's UB, even if it is currently working.


Field-by-field gradual initialization is explicitly described as incorrect in the documentation for assume_init_mut.

I would encourage you to do this instead:

let mut module_entry = MODULEENTRY32::default();
module_entry.dwSize = size_of::<MODULEENTRY32>() as u32;
let result = Module32First(module_snap, &mut module_entry);

Since this doesn't access uninitialized memory incorrectly, this is not UB.

1 Like

Thanks, completely overlooked that I could initialize my structs with default values and get rid of MaybeUninit completely where I don't need it.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.