-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Windows allocator is incompatible with passing heap allocations across DLL libraries with static std #131468
Comments
At least on Windows 7 and Windows 11, |
If two DLL's statically link the standard library, you should not use the rust abi between them. This is not the only place where there is global mutable state in rust. For example for panics when catching we explicitly check that the underlying exception was thrown by the same copy of the standard library to prevent UB in case of both copies being from a different rustc version. And even aside from that check having multiple copies of the panic count can easily result in a panic turning into an abort if it was caught by a different copy of the standard library. Would it be possible to dynamically link both DLL's against the same libstd.dll? That avoids duplication of the global mutable state of the standard library. |
At least theoretically, a function call can be more expensive for the happy path (which is just accessing/testing an atomic) even if that function returns a static. Whether or not it's measurable compared to allocating, I don't know, I haven't measured it. Admittedly I wouldn't have assumed so but apparently at least one person has measured improvements.
Yeah, we can walk back this alleged optimization (personally I'm open to that) but the general problem will remain. |
Right, I fully acknowledge it's a general problem, and I'm not expecting this to generally be fine. The chromuim component build has all kinds of issues caused by globals in various libraries. I'd just like to make this code not crash in this configuration.
One thing Chromium could do is to turn std into a "component" in this build, thus making it a shared library in that build configuration. There's other things we could do downstream to avoid this crash. The optimization and complexity here caused by the |
For what it's worth, I benchmarked removing the Here's my main.rs that I ran #![feature(test)]
extern crate test;
fn main() {
println!("Hello, world!");
}
#[cfg(test)]
mod tests {
use test::Bencher;
#[bench]
fn bench_alloc(b: &mut Bencher) {
b.iter(|| alloc_test());
}
fn alloc_test() {
let x: Box<i32> = Box::new(0);
test::black_box(x);
}
} I also did it again with a The HEAP variable seems to save about 2ns of time, for what that's worth, while an allocation/free can take more than 100ns (on my virtualized Windows machine). The time is within the noise when allocating 9001 i32s and not initializing them. Once memory initialization is involved, the time difference is completely buried within the noise. Results on HEAD:
Results with patch to remove HEAP variable:
I used this patch to remove HEAP and built std. Here's the .cargo/config.toml file I used, to point at the Chromium toolchain stuff. I used static CRT because that's what we use in our optimized builds. I presume that's the one that matters. [build]
rustflags = "-Clinker=C:\\src\\c\\src\\third_party\\llvm-build\\Release+Asserts\\bin\\lld-link.exe -Clink-arg=/winsysroot:C:\\src\\c\\src\\third_party\\depot_tools\\win_toolchain\\vs_files\\7393122652 -Ctarget-feature=+crt-static" I have |
Given two DLLs that contain statically-linked Rust code:
The Windows allocation code will crash due to the
HEAP
global variable being null in the second DLL:rust/library/std/src/sys/alloc/windows.rs
Lines 235 to 237 in a1eceec
The allocator code assumes that the allocation already happened in the same DLL.
On other build targets, this setup works fine.
it's not clear why the Rust stdlib goes to all the trouble with the
HEAP
global variable in the first place. It could just call GetProcessHeap() on each call to HeapAlloc() and HeapFree(). Could we get rid of theHEAP
variable?How did I run into this? You might wonder.
This build setup probably looks weird, but it is a fundamental (bad) thing that Chromium uses for debug developer builds, which we call our component build. We mark subsets of the build graph as
component
s and then everything inside the component is static-linked as usual, but the components are a cluster of DLLs. This breaks global variables and is generally problematic, you might think, and you're right. But it's also deemed to be important for making linking times on Windows debug builds reasonable.Chromium bug: https://crbug.com/372425130
The text was updated successfully, but these errors were encountered: