6 ms·
How exactly is pre-allocation safer? If you would ever like to re-use chunks of memory, then wouldn’t you still encounter “use-after-free” bugs?
by snicker7 4y ago
How exactly is pre-allocation safer? If you would ever like to re-use chunks of memory, then wouldn’t you still encounter “use-after-free” bugs?
- verdagon 4y agoThe approach can reuse old elements for new instances of the same type, so to speak. Since the types are the same, any use-after-free becomes a plain ol' logic error. We use this approach in Rust a lot, with Vecs.
- olig15 4y agoBut if you have a structure that contains offsets into another buffer somewhere, or an index, whatever - the wrong value here could be just as bad as a use-after-free. I don’t see how this is any safer. If you use memory after free from a malloc, with any chance you’ll hit a page fault, and your app will crash. If you have a index/pointer to another structure, you could still end up reading past the end of that structure into the unknown.
- verdagon 4y agoThat's just a logic error, and not memory unsafety which might risk UB or vulnerabilities. The type system enforces that if we use-after-"free" (remember, we're not free'ing or malloc'ing), we just get a different instance of the same type, which is memory-safe. You do bring up a valid broader concern. Ironically, this is a reason that GC'd systems can sometimes be better for privacy than Ada or Rust which uses a lot more Vec+indexes. An index into a Vec<UserAccount> is riskier than a Java List<UserAccount>; a Java reference can never suddenly point to another user account like an index could. But that aside, we're talking about memory safety, array-centric approaches in Zig and Rust can be appropriate for a lot of use cases.
- pjmlp 4y agoIn high integrity computing that is pretty much safety related, if that logic error causes someone to die due to corrupt data, like using the wrong radiation value.
- deleted 4y ago[deleted]
- tialaramex 4y agoBut, Java has exactly the same behaviour, the typical List in Java is ArrayList which sure enough has an indexed get() method. There seems to be no practical difference here. Rust can do a reference to UserAccount, and Java can do an index into an ArrayList of UserAccounts. Or vice versa. As you wish.
- verdagon 4y agoIn Java, you can hold onto a reference to the UserAccount directly, for as long as you want. The borrow checker, however, forces you to hold onto an index instead.
- anonymoushn 4y agoRight, it sounds like you are circumventing the borrow checker and then experiencing some of the classes of bugs it was supposed to prevent. And this seems common: https://www.youtube.com/watch?v=4t1K66dMhWk https://www.youtube.com/watch?v=4t1K66dMhWk
- verdagon 4y ago> Circumventing the borrow checker Programs often require inherent state with data that refers to other data. In these cases, one must circumvent the borrow checker, whether it be with indices, IDs, Rc, or whatever. The borrow checker simply does not allow changing data when someone has a reference to it (except for the rare case where we can use Cell). It's a myth that we can rewrite any program to not circumvent the borrow checker.
- veber-alex 4y agoIf you are holding indexes to a collection and plan to delete elements you will never use Vec. There are dedicated data structures for this [1] that will not let you access another item by mistake. [1] https://crates.io/crates/slotmap https://crates.io/crates/slotmap
- verdagon 4y agoYou should never use Vec in that situation, but we see it all the time. People love indexing into Vecs and reusing elements. One of my favorite alternatives is generational_arena [0] which also happens to be the library that inspired Vale's generational references! [0] https://docs.rs/generational-arena/latest/generational_arena/ https://docs.rs/generational-arena/latest/generational_arena...
- kaba0 4y agoThese are 1000 times worse than even a segfault. These are the bugs you won’t notice until they crop up at a wildly different place, and you will have a very hard time tracking it back to their origin (slightly easier in Rust, as you only have to revalidate the unsafe parts, but it will still suck)
- nine_k 4y agoNo; every chunk is for single, pre-determined use. Imagine all variables in your program declared as static. This includes all buffers (with indexes instead of pointers), all nested structures, etc.
- bsder 4y agoNormally you do this on embedded so that you know exactly what your memory consumption is. You never have to worry about Out of Memory and you never have to worry about Use After Free since there is no free. That memory is yours for eternity and what you do with it is up to you. It doesn't, however, prevent you from accidentally scribbling over your own memory (buffer overflow, for example) or from scribbling over someone else's memory.