12 ms·
Rust for C++ programmers – part 4: unique pointers
- pkulak 13y agoMan. Now I really want to read the next post...
- frozenport 13y ago>>The memory will not leak however, eventually it must go out of scope and then it will be free. Yes, if the function that called it lives for ever the point is perhaps moot, in an extreme case if it was called by 'main'.
- rcthompson 13y agoIf the pointer is returned all the way up to the main function, then it must be required for the lifetime of the program (or else the program is poorly designed). What point are you trying to make?
- frozenport 13y agoIt could also be a memory leak. For example, I have a for loop that keeps requesting a new pointer...
- rcxdude 13y agoOnly if you move the pointer into a vector or similar. just having loop { let x = ~"something"; } will not create a memory leak, as the pointer will be dropped and freed at the end of the loop.
- cmrx64 13y agoIf you're creating a new ~T in a loop, it will be freed after each iteration of the loop (ie, when the block ends). Witness for yourself: https://gist.github.com/cmr/f80c0a58e5b90021bb35 https://gist.github.com/cmr/f80c0a58e5b90021bb35
- masklinn 13y ago> For example, I have a for loop that keeps requesting a new pointer... Unless you put that pointer in a structure which lives forever, it will be freed as soon as a loop finishes: struct Foo { a: int, b: int } impl Drop for Foo { fn drop(&mut self) { println!("Drop {:?}", *self); } } fn foo(i: int) -> Foo { println!("Creating Foo with {}", i); Foo { a: i, b: 5} } fn do_thing(foo: &Foo) { println!("\tdo thing {:?}", *foo); } fn do_other_thing(foo: &Foo) { println!("\tdo other thing {:?}", *foo); } fn main() { for i in range(0, 5) { let a = box foo(i); do_thing(a); do_other_thing(a); } } will print Creating Foo with 0 do thing Foo{a: 0, b: 5} do other thing Foo{a: 0, b: 5} Drop Foo{a: 0, b: 5} Creating Foo with 1 do thing Foo{a: 1, b: 5} do other thing Foo{a: 1, b: 5} Drop Foo{a: 1, b: 5} Creating Foo with 2 do thing Foo{a: 2, b: 5} do other thing Foo{a: 2, b: 5} Drop Foo{a: 2, b: 5} Creating Foo with 3 do thing Foo{a: 3, b: 5} do other thing Foo{a: 3, b: 5} Drop Foo{a: 3, b: 5} Creating Foo with 4 do thing Foo{a: 4, b: 5} do other thing Foo{a: 4, b: 5} Drop Foo{a: 4, b: 5} (drop is ~equivalent to a C++ destructor)
- AlisdairO 13y agoI just tried the following: let mut blah = ~MyStruct{x: 3, y: 4}; for i in range(0,100000000) { blah = ~MyStruct{x: i + blah.x, y: i + blah.y}; } println!("{} {}", blah.x, blah.y); The memory usage didn't increase over time - the owned pointer frees when it gets reassigned.
- azth 13y agoSee this example for more details: https://news.ycombinator.com/item?id=7665617 https://news.ycombinator.com/item?id=7665617
- rdtsc 13y agoRust looks very exciting and promising. I see the hardest things for it to be not necessarily syntax and concurrency (which are very well done), but performance and getting to compete with C++11 (C++14), which actually seems to become fresh and interesting again. Performance is tough. I feel most often C++ is not chosen for its inherent cleanliness, elegance and beauty, but because there are no viable competitors at the given performance point. C++ compilers have been honed and tweaked for more than a decade now, so it will be a hard battle ahead.
- pcwalton 13y agoI feel pretty good about it. For one, we have significantly better aliasing information than C++, and we use most of the guts, including all the optimizations and code generation, of a C++ compiler (clang/LLVM). There are also some optimizations around move semantics that are open to us but not for C++ as standardized. That said, there are definitely performance bugs that have yet to be fixed. But I would definitely say most Rust code, if well-written, can be competitive with C++ today.
- seertaak 13y ago> There are also some optimizations around move semantics That piqued my curiosity -- would you mind going into a little more detail, or point me to somewhere where these are discussed?
- pcwalton 13y agohttps://github.com/mozilla/rust/issues/5016 https://github.com/mozilla/rust/issues/5016 is the main optimization (and we have more discussed but not written up). Since we have a very strict notion of liveness, we don't have to zero out moved data since the compiler can just not run the destructor.
- berkut 13y agoHow does one do intrinsics (SSE / AVX) in Rust - I guess they're just the exposed functions from emmintrin.h and the compiler calls them directly? How do you do ASM in Rust? Can you align memory in rust?
- bambam12897 13y agoI've been working C++ professionally for a couple of years and honestly I'm a huge fan - So I was excited to read about an alternative. After reading your 5 posts, I get the impression that RUST is mostly mildly useful syntactic sugar on top of C++. Here is my feedback: 1 - If memory management is a serious problem for the software you work on, I've never found the boost library lacking. This seems like the main selling point for RUST. Given the scope of the project: you guys must be doing something that is so different that it couldn't be rolled into a library - so I'm looking forward to your future posts to see if there is something here that I really am missing out on. 2 - I'm not a fan of the implicitness and I personally don't use 'auto' b/c it makes scanning code harder. I guess this is more of a personal preference. 3 - A lot of things are renamed. auto->let, new->box, switch->box You get the feeling that effort was put in to make the language explicitly look different from C++ 4 - the Rust switch statement don't fall through... This one was truly mind blowing. The one useful feature of switch statement got ripped it out! If you don't really need the fall through, I'd just avoid using them completely... 5 - I've never really seen an equivalent to boost (in combination to the STL) in other languages (maybe I didn't look hard enough). Could you maybe make a post about the RUST standard library? Libraries are always the deal breaker To that point, my last comment is maybe a little more wishy washy. The main reason I'm consistently happy with using C++ (and why I put up with the header files) is that everything is available. If you need to do X, and X has at some point been put into library by someone: you can be sure that that library will be available in C++. Since Rust seems so close to C++, does this mean that linking to C++ code is trivial? If I can seamlessly start programming parts of our codebase in RUST, that could potentially make a huge impact.
- pix64 13y agoThe 'let' keyword introduces a variable. It's not 'auto'. You can still declare variables types explicitly: 'let x: int = 5' 'match' is also much more powerful than 'switch'. You can match on several patterns, ranges of numbers, as well as use guards. http://rustbyexample.com/examples/match/README.html http://rustbyexample.com/examples/match/README.html
- jcmoyer 13y ago>1 - If memory management is a serious problem for the software you work on, I've never found the boost library lacking. This seems like the main selling point for RUST. Given the scope of the project: you guys must be doing something that is so different that it couldn't be rolled into a library - so I'm looking forward to your future posts to see if there is something here that I really am missing out on. I would say that Rust's defining feature is the borrow checker[1], which eliminates an entire category of pointer related errors at compile time. >3 - A lot of things are renamed. auto->let, new->box, switch->box You get the feeling that effort was put in to make the language explicitly look different from C++ Rust is strongly influenced by the ML family of languages. I believe that's where some of the keywords came from. >4 - the Rust switch statement don't fall through... This one was truly mind blowing. The one useful feature of switch statement got ripped it out! If you don't really need the fall through, I'd just avoid using them completely... Rust doesn't have a classical switch statement. Instead, it has a 'match' keyword that performs pattern matching on the input so you can easily destructure a complicated blob of data into more manageable pieces. This is also a concept borrowed from the ML family. If you really wanted to, you could write a macro that emulates the C style switch statement. >5 - I've never really seen an equivalent to boost (in combination to the STL) in other languages (maybe I didn't look hard enough). Could you maybe make a post about the RUST standard library? Libraries are always the deal breaker There's a great overview[2] of what the standard distribution contains on the Rust website. [1] http://static.rust-lang.org/doc/master/rustc/middle/borrowck/doc/index.html http://static.rust-lang.org/doc/master/rustc/middle/borrowck... [2] http://static.rust-lang.org/doc/master/index.html#libraries http://static.rust-lang.org/doc/master/index.html#libraries
- captainmuon 13y agoRust gives me the same feeling I had when learning C. I started with BASIC, then learned Java and a bit of Pascal, Perl, etc., but C was my first language with pointers. Now it seems silly, but understanding pointers was a huge step to me. There's a before and an after. Getting used to owned/transferable pointers seems to involve a similar step, although it's probably easier this time since I understand what they do. Btw., if you like this kind of intelligent pointers, Vala something similar [1], and the syntax seems a bit easier at first glance. You have owned pointers (and can transfer ownership), shared pointers (with reference counting) and unmanaged pointers. It uses reference counting for all the UI stuff (Vala is highly integrated with Glib and Gtk), since that is usually not performance critical and you'd rather be correct there. If you feel the need to do without reference counting, you can manage memory manually, too. [1]: https://wiki.gnome.org/Projects/Vala/ReferenceHandling https://wiki.gnome.org/Projects/Vala/ReferenceHandling
- NAFV_P 13y ago> Rust gives me the same feeling I had when learning C. I started with BASIC, then learned Java and a bit of Pascal, Perl, etc., but C was my first language with pointers. Now it seems silly, but understanding pointers was a huge step to me. You learned programming the right way round, unlike myself. One of the current problems with the web is that any old noob can learn any old language, so rather than following good advice and learning Python, I hacked C. One of the most interesting things about C is the more proficient you become, the more you use pointer to pointer to pointer of type array of pointer to function that returns a pointer to pointer of type array of pointer to function that returns pointer to void. Proper high level languages just go straight over my head, they're way too complicated.
- pcwalton 13y ago> You have owned pointers (and can transfer ownership), shared pointers (with reference counting) and unmanaged pointers. It uses reference counting for all the UI stuff (Vala is highly integrated with Glib and Gtk), since that is usually not performance critical and you'd rather be correct there. If you feel the need to do without reference counting, you can manage memory manually, too. That doesn't sound safe—what if unowned pointers outlive the owned pointer, and you get use-after-free? I don't believe it's possible to avoid pervasive reference counting or GC in a practical sense, and still be safe, without something like lifetimes built into the type system.
- kirab 13y agoWhat the heck is this? y: ~~~~~Foo
- akavel 13y agoI assumed it reads more or less like: Foo *****y; Or, probably, more like: std::unique_ptr<std::unique_ptr<std::unique_ptr<std::unique_ptr<std::unique_ptr<Foo>>>>> y;
- alkonaut 13y agoy is a pointer to a pointer to a pointer to a pointer to a pointer to an instance of Foo. What the author wanted to show was that there is automatic dereference: z = y.foo() Will just reference through all five pointers and call the method on the object directly.
- masklinn 13y agoA pointer to a pointer to a pointer to a pointer to a pointer to a Foo.
- stewbrew 13y agoI recently wondered whether it's possible to compile rust into a dll/so or whether there is a way to call rust from other languages (e.g. C, R, or ruby). All I found is that this isn't (easily?) possible because of rust's runtime. Is this true? If so, will it be possible to call rust from, e.g., C code? I'd like to have an alternative to c/c++ for writing native extensions for interpreted languages.
- Dewie 13y agoAlternatively you could write runtime-less Rust. I don't know if the offerings for this at this point is at the prototype stage or better, but it seems like something that they want to keep.
- rcxdude 13y agoIt's on the roadmap: there's plans to split the standard library into parts which require the runtime and parts which don't (as well as into parts which don't require malloc). As it stands you can write them, but you need to avoid parts of the standard library.
- steveklabnik 13y agoThe third production deployment of Rust is a Ruby extension written in Rust. https://air.mozilla.org/sprocketnes-practical-systems-programming-in-rust/ https://air.mozilla.org/sprocketnes-practical-systems-progra... (You'll have to scroll forward) And technically, it's a Ruby extension written in C. But the C is very small, and is mostly written in Rust. This is because Ruby's cexts use so many C macros, it was easier to make a shim then try to port them all to Rust.
- masklinn 13y ago> If so, will it be possible to call rust from, e.g., C code? I'd like to have an alternative to c/c++ for writing native extensions for interpreted languages. Yes. Technically it's already possible[0][1] but AFAIK it requires throwing out all (?) of the stdlib. rust-core[2] is an exploration of a runtime-less subset of the stdlib, which would ultimately be usable under a no_rt flag or something like that (at this point you have to disable the stdlib entirely and use rust-core instead) [0] https://github.com/mozilla/rust/issues/3608 https://github.com/mozilla/rust/issues/3608 [1] https://github.com/charliesome/rustboot https://github.com/charliesome/rustboot [2] https://github.com/thestinger/rust-core https://github.com/thestinger/rust-core
- coldtea 13y agoFrom the blog: >I have history with Firefox layout and graphics, and programming language theory and type systems (mostly of the OO, Featherweight flavour, thus the title of the blog). Hmm, what are "type systems" of "featherweight flavour"? Anything real or some inside joke? Or perhaps an elaborate way to say "not that complicated"? (Google mostly returns references to the same blog)
- nrc 13y agoFeatherweight Java (http://www.fos.kuis.kyoto-u.ac.jp/~igarashi/papers/fj.html http://www.fos.kuis.kyoto-u.ac.jp/~igarashi/papers/fj.html) was a seminal paper which showed type soundness for Java. The formal syntax was a subset of Java subset and preserved the interesting features in the semantics (as opposed to encoding a language in an extension of the lambda calculus, which is an alternative style of formalisation). So, "featherweight flavour" refers to formal type systems work which follows this style of formalisation.
- masklinn 13y agoI'd expect something along the lines of: > Several recent studies have introduced lightweight versions of Java: reduced languages in which complex features like threads and reflection are dropped to enable rigorous arguments about key properties such as type safety. We carry this process a step further, omitting almost all features of the full language (including interfaces and even assignment) to obtain a small calculus, Featherweight Java, for which rigorous proofs are not only possible but easy. > Featherweight Java bears a similar relation to Java as the lambda-calculus does to languages such as ML and Haskell. It offers a similar computational "feel," providing classes, methods, fields, inheritance, and dynamic typecasts with a semantics closely following Java's. A proof of type safety for Featherweight Java thus illustrates many of the interesting features of a safety proof for the full language, while remaining pleasingly compact. The minimal syntax, typing rules, and operational semantics of Featherweight Java make it a handy tool for studying the consequences of extensions and variations. You can see a few of his pubs on his website: http://www.ncameron.org/papers/index.html http://www.ncameron.org/papers/index.html