5 ms·
I agree that leaking memory usually gets its own category, rather than being shoveled under the "memory safety". That said, I'll play a bit of devil's advocate
by MaulingMonkey 5y ago
I agree that leaking memory usually gets its own category, rather than being shoveled under the "memory safety". That said, I'll play a bit of devil's advocate:
You can still have use-after-free bugs in a GCed language. A trivial example is calling methods on a closed/disposed/??? socket, file, or other handle. They don't result in the arbitrary memory corruption I'd typically consider a "real" memory safety issue, but they do result in bugs. In some cases, debug allocators and tools like address sanitizer can even surface such mistakes more quickly than similar code in a GCed languages. (Of course, in other cases, mistakes with non-GC memory cause bugs that are an absolute nightmare to repro and debug.)
More troubling is native interop, which I'd assume something like Synergy will definitely need to do plenty of to capture/forward keyboard/mouse input, bypassing the traditional window focus reliant input stack that the language may pre-provide safe bindings for. Failure to pin, or unpinning too early during an asyncronous operation, can cause your GC-allocated memory to shift around during GC compaction when native code was expecting it to remain in one place. The GC can also potentially outright reap GC-allocated objects that native code was using. I remember reading of nasty heisenbugs from Ruby C extensions forgetting to use RB_GC_GUARD to ensure VALUEs remain on the stack, where the GC can find them, when scanning for GC roots that keep objects alive - as an example.
Well, you can write similar bugs in non-GCed languages, but GCed languages aren't immune from these concerns. I've even bluescreened fairly modern Windows, with C# code, by sufficiently misusing SlimDX!
EDIT: links to the aforementioned reading:
http://timetobleed.com/the-broken-promises-of-mrireeyarv/ http://timetobleed.com/the-broken-promises-of-mrireeyarv/
https://news.ycombinator.com/item?id=2730286 https://news.ycombinator.com/item?id=2730286
- Rochus 5y ago> You can still have use-after-free bugs in a GCed language. A trivial example is calling methods on a closed/disposed/??? socket, file, or other handle. What prevents you from doing such things in Rust?
- MaulingMonkey 5y agoSuch operations often consume `self` in Rust, resulting in compile time errors: use std::io::{self, *}; fn main() -> io::Result<()> { let mut f = std::fs::File::create("asdf.txt")?; writeln!(f, "asdf")?; drop(f); // closes asdf.txt writeln!(f, "asdf")?; // error[E0382]: borrow of moved value: `f` Ok(()) } Full diagnostics: error[E0382]: borrow of moved value: `f` --> src/main.rs:7:5 | 4 | let mut f = std::fs::File::create("asdf")?; | ----- move occurs because `f` has type `File`, which does not implement the `Copy` trait 5 | writeln!(f, "asdf")?; 6 | drop(f); | - value moved here 7 | writeln!(f, "asdf")?; | ^^^^^^^^^^^^^^^^^^^ value borrowed here after move | = note: this error originates in the macro `writeln` (in Nightly builds, run with -Z macro-backtrace for more info) For more information about this error, try `rustc --explain E0382`. Of course, a socket timing out or a drive getting unmounted could still yank a handle out from under these APIs, and e.g. C++ still allows for using such zombie objects. There are also ways to help catch such bugs in GCed languages as well (be it ObjectDisposedException making such bugs shallower in C#, or using lambdas/blocks for scopes to turn continued object use into a syntax error:) # Ruby File.open("asdf.txt", "w") do |f| f.write("asdf") end f.write("asdf") # f wasn't in scope Ruby's dynamic nature means this will still fail at runtime, but similar patterns in C# can force compile time syntax errors for use after close. EDIT: You even see this pattern in Rust, occasionally, to limit reference lifetimes to avoid soundness issues (e.g. all the annoying `.with(...)` blocks you see when using thread_local! : https://doc.rust-lang.org/std/thread/struct.LocalKey.html https://doc.rust-lang.org/std/thread/struct.LocalKey.html ).
- Rochus 5y agoThat's interesting, thanks; with a GC language one would raise a runtime exception instead.