Live data from Hacker News

Uninitialized memory: Unsafe Rust is too hard

lucumr.pocoo.org

111–120 of 127 posts

Re: Uninitialized memory: Unsafe Rust is too hard

#111
post #109

Without any unsafe code this is simply: let role = Role { name: "basic", flag: 1, disabled: false, }; The language tries to prevent you from interacting with a `Role` object that's not fully initialized. `mem::zero()` could work, but then you'll have to turn the `&'static str` into an `Option ` or a raw pointer, to indicate that it might be null. You could also add `#[derive(Default)]` to the struct, to automatically…

> The language tries to prevent you from interacting with a `Role` object that's not fully initialized. I remember that after reading the Rust book, one of the first things I tried to do was to load a struct from a file. Like pseudocode: struct MY_STRUCT my_struct; read(file, &my_struct, sizeof(my_struct)); 2 lines of code.... It should be simple, right? RiGhT?! Well, the first stackoverflow answer involved unsafe an…

>It should be simple, right?

Well, no. If you want to have memory safe subset, you absolutely cannot initialize structs with random bag of bytes in general case. C let's you cut corners here, but in Rust you need to implement (de)serializing logic (no need for unsafe).

>Then I learned that structs are not laid out as declared (OMG!), etc. >It should be simple! I tried to create a variadic function and you can guess how it went.

This is only surprising if you have this weird assumption that things should work like they do in C + some extra.

Re: Uninitialized memory: Unsafe Rust is too hard

#112
post #109

Earlier quoted context omitted.

> The language tries to prevent you from interacting with a `Role` object that's not fully initialized. I remember that after reading the Rust book, one of the first things I tried to do was to load a struct from a file. Like pseudocode: struct MY_STRUCT my_struct; read(file, &my_struct, sizeof(my_struct)); 2 lines of code.... It should be simple, right? RiGhT?! Well, the first stackoverflow answer involved unsafe an…

>It should be simple, right? Well, no. If you want to have memory safe subset, you absolutely cannot initialize structs with random bag of bytes in general case. C let's you cut corners here, but in Rust you need to implement (de)serializing logic (no need for unsafe). >Then I learned that structs are not laid out as declared (OMG!), etc. >It should be simple! I tried to create a variadic function and you can guess h…

> in Rust you need to implement (de)serializing logic

Hmm. Well that sucks. It might be slower than reading into a struct directly (does more IO calls, there is more code to execute, probably uses more memory). My focus is on embedded applications, so "the less, the better".

> no need for unsafe

Can you point out an example on reading a bunch of structs from a file? Without std? Now I'm really curious.

> you have this weird assumption

You are probably right. I intended to use Rust in embedded as I said before so I thought a system language like Rust could fit. But you are right and the more I read (docs and comments like yours) I realize it's not C, and Rust may require extra steps and resources to achieve the same things I can do in C. With consequential hit on performance/code size/whatever, that it's a thing to consider seriously in constrained environments.

Re: Uninitialized memory: Unsafe Rust is too hard

#113
post #112

Earlier quoted context omitted.

>It should be simple, right? Well, no. If you want to have memory safe subset, you absolutely cannot initialize structs with random bag of bytes in general case. C let's you cut corners here, but in Rust you need to implement (de)serializing logic (no need for unsafe). >Then I learned that structs are not laid out as declared (OMG!), etc. >It should be simple! I tried to create a variadic function and you can guess h…

> in Rust you need to implement (de)serializing logic Hmm. Well that sucks. It might be slower than reading into a struct directly (does more IO calls, there is more code to execute, probably uses more memory). My focus is on embedded applications, so "the less, the better". > no need for unsafe Can you point out an example on reading a bunch of structs from a file? Without std? Now I'm really curious. > you have thi…

>Can you point out an example on reading a bunch of structs from a file? Without std? Now I'm really curious.

Not really, but here is really simple example:

  use std::fs::File;
  use std::io::Read;
  
  #[derive(Debug)]
  struct Point {
      x: i32,
      y: i32,
  }
  
  fn bytes2point(buf: [u8; 8]) -> Point {
      Point {
          // Slices to arrays is a bit unwieldy...
          x: i32::from_le_bytes(buf[..4].try_into().unwrap()),
          y: i32::from_le_bytes(buf[4..].try_into().unwrap()),
      }
  }
  
  fn main() {
      let mut buf: [u8; 8] = [0; 8];
      let mut file: File = File::open("data.txt").unwrap();
      Read::read(&mut file, &mut buf).unwrap();
      let point: Point = bytes2point(buf);
      println!("{:?}", point);
  }
It doesn't do any extra i/o compared to C. Std is only used for filesystem access and printing. It does require extra buffer.

Re: Uninitialized memory: Unsafe Rust is too hard

#114
post #93

Earlier quoted context omitted.

Even though Rust's Editions don't solve everything they make a huge difference and they also change the nature of the conversation around such evolution. I think the built-in array type is illustrative. In both languages (C++ and Rust) the initial 1.0 language offers a built in array type that is provided with built-in syntax and parsing but isn't as good as the user-made container types, so on day one the situation…

I don't buy into editions, for me I hardly see them any different from language version switches available across programming languages. Mainly, because: 1 - They require the whole code, including all third party dependencies to be available to the compiler; 2 - There is the issue about possible inconsistencies across Rust compilers, when they start to be more widespread; 3 - They are relatively constrained the scope…

The requirement to have all the source if you're not happy with C-style ABI boundaries comes from Rust itself not from its Editions. C++ leaves a bunch of performance on the table here because it insists on pretending your code from last century should get to dictate how a CPU designed last year works.

Hyrum's law will indeed bite multiple Rust implementations, as it already bites Rust on non-x86 CPUs because a low level language cannot entirely conceal implementation details. This is already a huge leap over C++ where you get to tickle previously undetected Undefined Behaviour if you change compilers because (safe) Rust stays safe even if you're astonished that e.g. documentation saying "the order is not defined" really means "the order is not defined" despite the fact you tested it on your laptop last week and that's how it worked. Your bad program might have bugs but it doesn't suddenly exhibit nonsense behaviour.

Fundamentally Rust's Editions are about the fact that we don't get it right first time every time. In C++ having settled on the claim that (quoting Stroustrup) "this array concept is inherently low level" the built-in array is basically abandoned as unusable garbage forever because to do otherwise would admit a mistake. In contrast Rust says sure, arrays don't yet have all the features you expect of first class containers, we will improve the language to deliver that.

I think this is a healthier philosophy and it's already successful. It isn't a panacea, but it is a very noticeable improvement.

As to taking care of items that are yet to stabilise, what's to see here? Even for something like generators that is far from finished, the keyword is reserved already, you probably wouldn't wait for an edition to land it, once it was stable you just flip the toggle and it works.

Re: Uninitialized memory: Unsafe Rust is too hard

#115
post #107

Earlier quoted context omitted.

(All responding to 1) A. Binary dependencies were a mistake. B. No, editions absolutely do not require all dependencies to be fully available in source. Editions are purely a front end thing and as long as you have enough info for the api/abi, you're fine. C. Headers are still source code. You cannot use any dependency without partial source, meaning we'd be stuck with that anyway.

C headers don't give away implementation. If Rust doesn't want the enterprise and game development markets it is ok, there is enough space for all.

Enterprise is very much a trailing indicator. On the whole Enterprise will adopt Rust the same way it adopted Version Control and the Internet, years late and reluctantly. Nobody making those decisions knows the first thing about technology, but that cuts both ways. It means there aren't going to be executives at Mondelez International chasing their software engineers to use Rust because it's a good idea, but it also means despite lobbying by C++ consultants, those executives don't care that an internal team started using Rust for a new project.

As to Game Development, well, one of the things Rust has been trying to do is avoid toxic people and if you wanted a concentrated supply of toxic people the video game industry is where you'd look. I expect there will be a lot of Rust in or near video games in the next decade, but I already pity the people working on them.

Re: Uninitialized memory: Unsafe Rust is too hard

#116
post #112

Earlier quoted context omitted.

>It should be simple, right? Well, no. If you want to have memory safe subset, you absolutely cannot initialize structs with random bag of bytes in general case. C let's you cut corners here, but in Rust you need to implement (de)serializing logic (no need for unsafe). >Then I learned that structs are not laid out as declared (OMG!), etc. >It should be simple! I tried to create a variadic function and you can guess h…

> in Rust you need to implement (de)serializing logic Hmm. Well that sucks. It might be slower than reading into a struct directly (does more IO calls, there is more code to execute, probably uses more memory). My focus is on embedded applications, so "the less, the better". > no need for unsafe Can you point out an example on reading a bunch of structs from a file? Without std? Now I'm really curious. > you have thi…

I'd be surprised if you see that Rust code is significantly slower than equivalent C code; this isn't how it pans out in most benchmarks. The killer for Rust is executable binary size, which even with no-std and other tricks can still balloon to an enormous size.

Re: Uninitialized memory: Unsafe Rust is too hard

#117
post #112

Earlier quoted context omitted.

> in Rust you need to implement (de)serializing logic Hmm. Well that sucks. It might be slower than reading into a struct directly (does more IO calls, there is more code to execute, probably uses more memory). My focus is on embedded applications, so "the less, the better". > no need for unsafe Can you point out an example on reading a bunch of structs from a file? Without std? Now I'm really curious. > you have thi…

>Can you point out an example on reading a bunch of structs from a file? Without std? Now I'm really curious. Not really, but here is really simple example: use std::fs::File; use std::io::Read; #[derive(Debug)] struct Point { x: i32, y: i32, } fn bytes2point(buf: [u8; 8]) -> Point { Point { // Slices to arrays is a bit unwieldy... x: i32::from_le_bytes(buf[..4].try_into().unwrap()), y: i32::from_le_bytes(buf[4..].tr…

Thank you.

I see. I'm looking now at how to load DOOM WAD files in Rust (https://github.com/bjt0/rs_wad/blob/master/src/wad.rs#L105) as an example, and I see it uses your method (even if it seems to store each piece in individual variables to then copy them into the struct).

It's not as straightforward as one would expect (as you say, it requires an extra buffer and parsing, but no extra IO). I surely wouldn't get to the solution by myself.

Re: Uninitialized memory: Unsafe Rust is too hard

#118
post #112

Earlier quoted context omitted.

>It should be simple, right? Well, no. If you want to have memory safe subset, you absolutely cannot initialize structs with random bag of bytes in general case. C let's you cut corners here, but in Rust you need to implement (de)serializing logic (no need for unsafe). >Then I learned that structs are not laid out as declared (OMG!), etc. >It should be simple! I tried to create a variadic function and you can guess h…

> in Rust you need to implement (de)serializing logic Hmm. Well that sucks. It might be slower than reading into a struct directly (does more IO calls, there is more code to execute, probably uses more memory). My focus is on embedded applications, so "the less, the better". > no need for unsafe Can you point out an example on reading a bunch of structs from a file? Without std? Now I'm really curious. > you have thi…

Rust works great in embedded. You do have to learn some things about how to get binary sizes down, depending on how resource constrained you are. If you're on a device that's running Linux, you probably don't need to think about it at all. If you're on a device and writing 100% of the code yourself, you may have to watch out for certain things, like formatting code, that can add a bunch of bloat, and choose alternatives.

At work we have a de novo microkernel we're using for the firmware of a few things inside of our product. A recent build we did to check on binary size of OS + 5 simple tasks using 22kb of flash and 3.5 kb of RAM. Those tasks are all separately compiled programs, it all gets put together on one single image to flash.

If you're talking 8 bit micros, you run into platform support issues before you even get to the binary size stuff, but if you're on Arm, even the low end, size is not the primary issue when it comes to doing Rust projects.

Re: Uninitialized memory: Unsafe Rust is too hard

#119
post #78
post #63

Earlier quoted context omitted.

The point is to make points in a simple environment. Anything small enough to clearly make points about unsafe Rust is almost certainly small enough to be done in safe Rust, defeating the purpose.

If it’s too big for an example, it’s almost certainly too big for “trust me, I know this is safe”.

I don't see how you can make this claim. An example is meant to be understandable after a cursory introduction and communicate an idea to the reader. If it takes me a day to understand the "example", it's not useful as an example, but real problems often take that long to completely understand in any language.

Re: Uninitialized memory: Unsafe Rust is too hard

#120
post #15
post #11

Earlier quoted context omitted.

Why was this downvoted? Rust may be the "most loved" language, but after a few weeks with it, I don't love it. We've got to face the reality that it makes simple things way too complicated. In fairness, I have found the compiler errors to be extremely helpful. They often tell me exactly what to fix. But honestly, they shouldn't have to do that. The syntax should have been obvious from the beginning, as it is in most…

What syntax "should have been obvious from the beginning"? I always felt like most things in Rust are around as simple as they could be, for the things the language is trying to do.

Stuff like

    type TestResult = Result>
is not obvious nor simple and makes a joke of the claim that Rust is simpler than C++ in error handling. Damn, I prefer straightforward C++ exceptions after seeing stuff like this.
Post reply on HN