Rust and RAII Memory Management - Computerphile

  Рет қаралды 210,659

Computerphile

Computerphile

Күн бұрын

Rust has memory management built in. Ian Knight takes us through some of its features.
Garbage Collection video: • Garbage Collection (Ma...
/ computerphile
/ computer_phile
This video was filmed and edited by Sean Riley.
Computer Science at the University of Nottingham: bit.ly/nottscomputer
Computerphile is a sister project to Brady Haran's Numberphile. More at www.bradyharan.com

Пікірлер: 831
@refactorear
@refactorear Жыл бұрын
9:19 I would say exactly the opposite, in this situation the best for your program is to crash, the worst is to get garbage and continue as if nothing had happened as it might takes months, years or decades to find out such a problem (especially when dealing with processing data and not knowing the kind of output you should expect). What usually happens, though, is that you get intermittent crashes depending on the memory values you get from that dangling pointer. Pretty sure the constructor and destructor in the C++ version needs to have the same name as the class, but that's besides the point of the video.
@Fs3i
@Fs3i Жыл бұрын
I was gonna write that. The best case for a UAF is usually a crash, rather than silent data corruption, or revealing random memory. Both of them are security/safety risks, which can undermine everything your program does.
@bkucenski
@bkucenski Жыл бұрын
Yep. When things break loudly, it's a big motivation to go fix it. You can also log exactly where the crash happened and the state to track what caused it so you can prevent the problem in the future.
@-dubu
@-dubu Жыл бұрын
Fail early and loudly
@crateim
@crateim Жыл бұрын
this! crashes are problems that actually got *detected* and *prevented* - crashes are your friends
@ClifBratcher
@ClifBratcher Жыл бұрын
💯 The development time (money) involved in debugging the garbage cases is dramatically larger than failing fast.
@cowslaw
@cowslaw Жыл бұрын
Rust’s borrow checker is one of the most powerful and strict features of any language I’ve ever used, and it’s absolutely wonderful!
@nicholas1460
@nicholas1460 Жыл бұрын
Let's make a Groovy for Rust so we can ignore all that and turn it into an interpreter.
@alucard87
@alucard87 Жыл бұрын
@@nicholas1460 absolutely! Lets bring gstrings everywhere!🎉
@nicholas1460
@nicholas1460 Жыл бұрын
@@alucard87 The pervs have surfaced. Anyone has anything to do with the Groovy language is responsible for what they do.
@KX36
@KX36 Жыл бұрын
meanwhile, every rust user: "unsafe { ... }"
@legotechnic27
@legotechnic27 Жыл бұрын
There's stricter features in Dafny, but I'm not sure those are "absolutely wonderful". They certainly are very interesting though.
@barbiefan3874
@barbiefan3874 Жыл бұрын
09:20 - it's pretty much the other way around. Best case - your program crashes, worst - you get wrong data and use it.
@256shadesofgrey
@256shadesofgrey Жыл бұрын
Depends on the program, where exactly in the program this problem appears, and how often it does so. For example if the value was storing the color information for a single pixel, and that value is garbage once every 10 million outputs, and all the program does is display images on the screen, I'd rather have that single pixel flicker with random colors once every 5 frames than have the program crash. At least as a user.
@YouPlague
@YouPlague Жыл бұрын
@@256shadesofgrey This thinking is what leads to scanners giving you wrong numbers in your tax reports, look up "Xerox randomly changes numbers". The program should crash and make the developer fix it immediately, not try to ignore it forever.
@anafabula
@anafabula Жыл бұрын
That "bob" variable you tried to use three times doesn't exist. And why not show the compiler output? It's very friendly
@chuxmyk
@chuxmyk Жыл бұрын
Exactly. I was going to ask this. I kept searching for where it was defined since the argument passed was “b” and none in func_1.
@-dubu
@-dubu Жыл бұрын
It’s not a rust tutorial, it’s explaining the idea of a borrow checker which it does fine
@jiayeelow
@jiayeelow Жыл бұрын
Thanks for clarifying, I was thinking if somehow 'bob' and 'b' are the same variables...
@ze_rubenator
@ze_rubenator Жыл бұрын
@@-dubu Still wary of learning anything from someone who doesn't appear to know what they're doing.
@a.modestproposal2038
@a.modestproposal2038 Жыл бұрын
This kind of sloppiness does a real disservice to the channel and the intent of the video. You can't be bothered to COMPILE all your examples? Or at least "*" annotate the errors in the video? Such obvious errors are a disappointing distraction that pollutes the message.
@cno9984
@cno9984 Жыл бұрын
I like how neither his C++ or Rust code snippets would compile.
@badassopenpolling
@badassopenpolling Жыл бұрын
correct hahaha
@KaneYork
@KaneYork Жыл бұрын
The C++ has extra sneaky [Undefined Behavior] too, because he used `delete` instead of `delete[]`.
@MS-ib8xu
@MS-ib8xu Жыл бұрын
I was wondering about that... I was thinking "surly they would have caught that, maybe it is a new feature in C++, the constructor can just be called Foo"
@leogama3422
@leogama3422 Жыл бұрын
That's what 'pseudocode' means. It's for other fellow humans, not computers...
@klittlet
@klittlet Жыл бұрын
Needless to say that is just for the purpose of explanation
@LuizDahoraavida
@LuizDahoraavida Жыл бұрын
5:50 in C++ you need to tell the compiler if what you're deleting is an array with delete[] instead of delete. In that example the memory won't have been freed properly.
@LuizDahoraavida
@LuizDahoraavida Жыл бұрын
I guess this just goes for show on how easily memory leaks can happen when the programmer is responsible for the memory management.
@kwanarchive
@kwanarchive Жыл бұрын
@@LuizDahoraavida Just use std::vector.
@seth3129
@seth3129 Жыл бұрын
@@LuizDahoraavida now you're getting it :) this is why rust was created in the first place: to eliminated a whole class of bugs caused by common and easy to make mistakes
@LuizDahoraavida
@LuizDahoraavida Жыл бұрын
I just hope that wasn't on purpose
@kwanarchive
@kwanarchive Жыл бұрын
@@seth3129 std::vector already existed from the beginning.
@FF_Fanatic
@FF_Fanatic Жыл бұрын
It seems a little apples-to-oranges to have a raw pointer in C++, but have a vector in Rust. Both of the languages have a suitable vector type that uses low-level operations under the hood and packages that up into a nice-to-use type with the hard work done for you. Using the video's examples for the two languages makes it easy for people who aren't familiar with them to walk away with a very incorrect view of C++ that remains pervasive in the field, but doesn't reflect how ordinary code is written at all. The Rust comparison should come in at the point where it starts to offer more guarantees and functionality than what C++ can offer, and point out that it's part of the language rather than static analysis. Even moving (which C++ has too, just different) isn't so much about one owner for something like a vector (the vector already represents a single owner of its memory) as it is about not needlessly copying the vector. Either way works, but one makes copies explicit. There are other contexts where it's more about a single owner for a resource. Borrow checking and trying to use something after it's been moved from are where Rust really starts to bring more to the table in this regard than static analysis with accompanying rules on how to write code so the analyzer can reasonably work with it.
@claytorpedo
@claytorpedo Жыл бұрын
This is the same problem I have with most Rust vs C++ comparisons -- you get someone who appears to have virtually no knowledge of C++ that isn't at least two if not three decades out of date confidently saying why their insanely contrived example that no real person would ever do could be better in Rust. I strongly suspect there are things that _would_ be nicer for me in Rust, but instead I just keep seeing crappy Rust salespeople that don't know any C++ but try to pretend that they do. This person doesn't even seem to know how the very basic fundamentals like how constructors and new/delete works (this feels too extreme to be live-demonstration nerves, and insane they didn't doctor it in post), so I'm very doubtful they ever knew anything about C++ at all. From what I understand, most of what Rust brings to the table is advanced static analysis, which is great, but C++ has a decent amount of that too (e.g. use-after-move or use-after-free).
@TheJaguar1983
@TheJaguar1983 Жыл бұрын
Yeah, happens a lot. I find a lot of Rust programmers are super into it, espousing all of it's pros, why everyone should use it and usually comparing it to C++. There's also an element of functional vs object-oriented where they all espouse functional or functional-style programming to be *always* superior to OOP despite the fact that OOP is still one of the most common programming paradigms in the world. They all seem to be drinking for the same fountain that says "this is why Rust is better than C++", but don't actually know anything about C++ beyond the base language and usually the 98 standard. Rust is kind of a cult and those who love it think every other language is terrible, especially C++. Personally, I love Python and C++, but I'll use whatever suits the task best.
@bruhe_moment
@bruhe_moment Жыл бұрын
​@@claytorpedothe advantage of rust isn't that it *offers* static analysis, it's that it *forces* static analysis by default. Someone who knows very little C++ is very likely to make this sort of mistake without knowing how it could've been prevented. Someone who knows very little Rust won't make this mistake because the compiler defaults don't allow for it.
@trapfethen
@trapfethen Жыл бұрын
The video is not demonstrating the Best Practices of both languages and how THEY differ. It is demonstrating the MINIMUMS of the language and how they differ. You can constrain C++ to get much of the same benefits as rust, with the added boilerplate, static analysis configurations, and code-style enforcement that comes with that. Even with all those things, it is still POSSIBLE to create these kinds of bugs because the language allows these unsafe operations BY DEFAULT and won't warn or flag that you are doing something that may cause issues. In rust, if you wish to do these types of operations for the few valid use-cases where they are unavoidable, you HAVE to tag that block as unsafe. In the event of a crash, that is going to be the FIRST place you look.
@TheJaguar1983
@TheJaguar1983 Жыл бұрын
@@trapfethen Thank you for providing a balanced analysis.
@br3adina7or
@br3adina7or Жыл бұрын
The reason you can't borrow mutably and immutably at the same time isn't because one function is expecting the data to be unchanging while another is expecting it to be mutable. If that was the case, as you are presenting, multiple mutable references would be allowed at the same time, when they very much aren't. Mutable references are meant to be exclusive so there's only ever one point of mutation for a given piece of data (and no immutable references at the same time), which is done in order to avoid data races and the such. This is why mutable references are often called exclusive references and immutable references are often called shared references. This principle is also applicable to `Rc`, which was mentioned. Rc basically gives shared references to the data, but it cannot be mutable; to have shared mutable data, one would have to use one of the interior mutability data structures (in the case of an `Rc`, you'd probably want a `RefCell`). I think it's important to make this clear when introducing the topic of references in Rust, because one of the core design principles is "fearless concurrency", and as such that is baked into its fundamental ownership principles. That is to say, these concepts are inherently tied in Rust. I don't know if this was an intentional simplification, but it's something that shouldn't've been omitted imo. As an aside, `Rc` and `Arc` aren't really like garbage collection. Like, they can be used like garbage collection, but basically instead of having a garbage collector go through the memory and seeing what should be dropped, `Rc` and `Arc` keep an internal counter and then increment it when cloned and decrement it when dropped. When an `Rc`/`Arc` is dropped and there's no more references, it just drops the underlying data. This means that using these smart pointers has a slightly different cost to the equivalent code in a garbage collected language. (Though this isn't really a major point.)
@valcron-1000
@valcron-1000 Жыл бұрын
GC is not just mark and sweep. Reference counting is a form of garbage collection
@pcfreak1992
@pcfreak1992 Жыл бұрын
I was going to post the same comment but you worded it better than I could have 😅
@mokuzzai8906
@mokuzzai8906 Жыл бұрын
also having multiple mutable references might cause data to become invalid. imagine taking a eference to the first item in a vector, and then overtiting the vector with an empty one. now our reference points to unitialized memory
@trisinogy
@trisinogy Жыл бұрын
Basically you pretended to "fix" something the video doesn't say in the first place, and failed to do so. I am used to this pointless pedantry on StackOverflow: not ready to face it here on YT, frankly.
@peter9477
@peter9477 Жыл бұрын
@@valcron-1000 I think the term GC is often misused that way, but I don't think it's correct. Python, for example, has a garbage collector, but it also has ref counts, and the GC is only there to clean up things the ref counting can't handle fully (like cycles). You can't have garbage collection without a garbage collector, and Rust definitely doesn't have one (any more).
@deconline1320
@deconline1320 Жыл бұрын
Even though the goal here was to demonstrate Rust RAII mechanism, it's worth mentioning that modern C++ provides equivalent concepts using unique_ptr and moves. Nowadays, you rarely need to delete memory manually in C++.
@bertiesmith3021
@bertiesmith3021 Жыл бұрын
You can still get dangling references pretty easily. Rust solves this with lifetime analysis. This can often be picked up in c++ through static analysis but Rust guarantees that dangling references won’t compile. The c++ is very poorly constructed - just accessing the data() function of std::vector would have been a better example to construct a dangling reference.
@TheJaguar1983
@TheJaguar1983 Жыл бұрын
It's the usual Cult of Rust propaganda: Rust is the best, everything else is bad, especially C++
@slyfox3333
@slyfox3333 Жыл бұрын
@@TheJaguar1983 C++ Stockholm syndrome in action
@TheJaguar1983
@TheJaguar1983 Жыл бұрын
@@slyfox3333 Typical one-eyed Rust fanaticism.
@slyfox3333
@slyfox3333 Жыл бұрын
@@TheJaguar1983 cope
@FPSMinecraftable
@FPSMinecraftable Жыл бұрын
Shouldn't constructors in C++ have the same name as the class?
@Hexalyse
@Hexalyse Жыл бұрын
If this was the only error in this video. Most variable and parameters names were wrong in the Rust example (n becoming bob, b, becoming bob, etc.). I liked the video but it was a mess. Trying to compile the code to show what it does would have allowed to detect those problems.
@AlFredo-sx2yy
@AlFredo-sx2yy Жыл бұрын
@@Hexalyse also delete instead of delete[], among other things, filling this video with tons upon tons worth of UB.
@Finkelfunk
@Finkelfunk Жыл бұрын
@@Hexalyse That is the issue with academic CS though. They are more interested in concepts and less in being code monkeys. They can design the most complex ideas and constructions, but in the end the people that work with the language on a daily basis will know a language better than they do.
@NeatNit
@NeatNit Жыл бұрын
@@Hexalyse It seems to me like all, or nearly all of these errors would have been caught if he just tried to compile his code after each demonstration. And actually *demonstrate.* But to be fair, he seemed a bit nervous in front of the camera and I don't blame him for getting lost. Next video will be better, I'm sure of it :)
@jongeduard
@jongeduard Жыл бұрын
@@Hexalyse Explaining and coding at the same time is not the best option for everyone I guess! 😆😁 Probably it would have been a better idea to first write and test all code first before showing it in a presentation. Explanation was fine though.
@GingerGames
@GingerGames Жыл бұрын
This video conflates RAII and ownership semantics quite a bit. This is a common misconception but if this is meant to be an introduction to either concept, this will most definitely confuse a newcomer to these concepts. You can explain Ownership Semantics without ever referring to RAII whatsoever and vice versa. Ownership semantics can be used to aid with a few issues that RAII in C++ causes (such as over use of copy constructors) but they solve different orthogonal problems entirely. C++11 onwards also has all of these ownership semantics (rvalue references, std::move, std::forward, etc), but they are an opt-in thing rather than something that is required like in Rust. Also, if you are wanting to reduce resource usage as much as possible, RAII is not the right tool for you and will most likely cause you to waste more memory than other approaches.
@kwanarchive
@kwanarchive Жыл бұрын
How does RAII cause you to waste more memory?
@zsomborhollay930
@zsomborhollay930 Жыл бұрын
RAII don't waste any resource, it's just a method to handle object states.
@noahhounshel104
@noahhounshel104 Жыл бұрын
I'm not sure I agree at all. This video isn't confusing RAII and ownership semantics at all, but is illustrating how RAII must be handled and enforced for it to work properly. To allow RAII to work at all, the borrow checker/ownership semantics have to be enforced. How is this conflating RAII and ownership semantics? I'm also unsure how RAII is "wasting memory" to be honest. Rust automatically drops things that go out of scope, but you can also drop things at any point.
@GingerGames
@GingerGames Жыл бұрын
@@noahhounshel104 ​ @kwanarchive ​ @Zsombor Hollay RAII on its own does not necessarily waste memory compared to other approaches, however the general culture assumes RAII means you should allocate singular things instead of thinking about your allocation separately from your single objects. As a result, a lot of memory is wasted because you off-load the allocation aspect to the single object, whereas RAII could still be useful if you did not do this. Another issue with C++ specifically is that they conflate construction/destruction with allocation/deallocation. It is extremely useful to want to allocate an object and then construct it at a later time, destruct it and then deallocate it at a later date, but due to the way C++ has been designed and the culture around C++, most people couple them together (making things bad). Constructors and destructors also do not "return a value" meaning that the only way you can signal something may have gone wrong is by throwing an exception (which might be a huge issue depending on the problem space). This is why many people will just use explicit `init` and `destroy` functions/methods instead of relying on the ctors/dtors, thus bypassing many of the features of RAII. I can give you loads of real world examples of codebases that use RAII heavily that are extremely wasteful of memory (compared to other approaches). And to clarify, RAII is not inherently wasteful but the culture around it and how it the languages that have tend to be designed nudge you to use it in such a way that is extremely uncaring about memory allocations by making them hidden.
@noahhounshel104
@noahhounshel104 Жыл бұрын
​@@GingerGames Eeehhhh. I suppose you can view RAII as "wasteful" if you are never deferring the creation of the objects to a later date, but in the Rust world doing so would just be an Option which is useful/important for a whole host of reasons besides having deferred allocation.
@kadlubom
@kadlubom Жыл бұрын
Shouldn't the constructor be 'Bob' not 'Foo' though?
@Faladrin
@Faladrin Жыл бұрын
I've not coded in C/C++ for a long time and I was having an aneurism when I saw that and wasn't sure if the code was wrong or my memory. Thanks for the comment letting me know I was right!
@Am6-9
@Am6-9 Жыл бұрын
I think its the other way round, the Class should be called Foo, not Bob…😊
@alcoholrelated4529
@alcoholrelated4529 Жыл бұрын
@@Am6-9 yeah, Bob should be called Robert
@tropicbliss1198
@tropicbliss1198 Жыл бұрын
It’s worth noting that rust has type inference, so you don’t have to specify your type every declaration of a variable
@johnyepthomi892
@johnyepthomi892 Жыл бұрын
@MenaceInc Well it would be a shame if it doesn’t 😂
@NuclearCraftMod
@NuclearCraftMod Жыл бұрын
@MenaceInc While you’re correct, C++‘s type inference, which is similar to Java’s, C#’s, etc. isn’t _quite_ as powerful as Rust’s, which is more like those found in functional-first languages. For example, in C++, you can’t write something like “auto x;”, while “let x;” is valid in Rust (provided the type of x actually can be uniquely inferred by how it’s used).
@konga8165
@konga8165 Жыл бұрын
If you have rust-analyzer installed you also get phantom type hints inline with your code which makes it so nice to read. No need to hover over variables to see the type like other languages. This seems small but it's so nice.
@jakubrogacz6829
@jakubrogacz6829 Жыл бұрын
@@NuclearCraftMod That is not a problem of language but of compiler standards.
@HoloTheDrunk
@HoloTheDrunk Жыл бұрын
@@konga8165 Many of the popular languages's LSPs have that kind of functionality though..? It's just returning more information to the editor following the LSP standard.
@mihir2012
@mihir2012 Жыл бұрын
I think this was explained quite poorly. You can write as much garbage code in any language you want, including rust. What matters is that when you try to compile the code, the rust compiler rejects much more (memory related) garbage than the c/c++ compiler does. Whereas c/c++ will allow you to get to runtime and may or may not crash then, rust doesn't allow you to get to runtime at all until you have fixed these issues. And not once you showed any compiler output at all. Which is also probably why you kept using variables that don't exist at all.
@sobanya_228
@sobanya_228 Жыл бұрын
Rust is like switching to a properly strictly typed language after coding in some poorly typed codebase in a gradually typed language.
@fllthdcrb
@fllthdcrb Жыл бұрын
21:01 You also can't have a mutable reference to an immutable variable, which Ian had at this point. And regarding mutable and immutable references, it's not just that you can't have both of those, you can't have _any_ other references, mutable or immutable, if one of them is mutable, for similar reasons. (It's a little more subtle, though. For these purposes, Rust only cares about the span of execution when the variable is actually used. That's why the example with moving an object from one variable to another is fine, because after that the first variable isn't used. In the same way, you can declare and use multiple mutable references to the same object in the same scope, as long as the regions where they're used don't overlap.)
@konga8165
@konga8165 Жыл бұрын
Huge fan of Rust. I've been writing it in production for over a year now and it's been a dream to work with.
@germandkdev
@germandkdev Жыл бұрын
Thank you for this explanation of RAII, it was really interesting. But nearly all examples shown wouldn't run as either variables or methods are wrongly named. (Foo constructor in Bob, bob instead of b in all rust functions)
@JR-mk6ow
@JR-mk6ow Жыл бұрын
I work as frontend and I've started using Rust because I was missing messing around a low-level language. I'm in love! It's harder than JS (and way slower to build anything) but the borrow checker and the compiler are so so so good.
@pyyrr
@pyyrr Ай бұрын
just use c++ rather than an esoteric language like rust
@h-0058
@h-0058 Жыл бұрын
Nice video, the Rust borrow checker is pretty cool, but the C++ comparison didn't make much sense. C++ has had smart pointers for 12 years now (maybe more with boost), which get rid of all the problems except dangling references. You never write new and delete in C++, you never use raw pointers that own memory, you can move or only "borrow". The only thing where standard C++ will not help you is if you borrow a pointer and try to access it after the owning pointer deleted the memory (so dangling references).
@hanifarroisimukhlis5989
@hanifarroisimukhlis5989 Жыл бұрын
Smart pointer still sucks though. Not everyone will use it, and adds complexity. Atleast Rust understands what you're doing and prevent errors before you spend hours debugging.
Жыл бұрын
There are a few more things C++ won't help you with but yeah, this was kinda strawman argument.
@valizeth4073
@valizeth4073 Жыл бұрын
C++ has had RAII capabilities since the 80's even, it was just made more nicely with the addition of move semantics.
@toby9999
@toby9999 Жыл бұрын
I still use new and delete and never have a problem with it.
@TheJaguar1983
@TheJaguar1983 Жыл бұрын
@@hanifarroisimukhlis5989 Not true. Smart pointers are excellent. On the other hand, the time you save on debugging with Rust, you waste fighting the borrow checker.
@myronkipa2530
@myronkipa2530 Жыл бұрын
Some of the things Rust does the right way: 1. RAII or memory ownership model - follow few rules and forget about memory leaks 2. Traits composition instead of trait inheritance. 3. Powerful enums/unions - can hold values. You have to consider all cases 4. Pattern matching 5. No NULL. Instead - enum with optional value 6. Powerful macros My main complaint with rust is that compiler won't let me be silly and write bad code. This also means it won't let you shoot yourself in the foot. But the learning curve is a bit steep. Rust is so different from other languages
@ifcoltransg2
@ifcoltransg2 Жыл бұрын
Rust is inconvenient to prototype things in. That's probably why we see a lot of Rust rewrites of existing programs, that already got prototyped decades ago.
@0x5DA
@0x5DA Жыл бұрын
@@ifcoltransg2 for some stuff. though, i actually find myself specifically leaning to rust to prototype in, because the way one lays state out makes it a lot easier to understand how the program would work, for me
@ifcoltransg2
@ifcoltransg2 Жыл бұрын
@@0x5DA I did overgeneralise. I guess Rust's type system is great when you want to make sure things end up correct and well structured. It gives you some support there to create a solid foundation. But I do find, for the kind of project you just want to get working, it's easiest to throw up some Python onto the screen first, rewrite it in a type system after.
@0x5DA
@0x5DA Жыл бұрын
@@ifcoltransg2 i get that, for making it work! no worries
@HoloTheDrunk
@HoloTheDrunk Жыл бұрын
​@@ifcoltransg2 After using rust for personal projects and then nearly a year in production, I now find it much easier to prototype complex ideas in. The biggest help it provides is in easily helping you design your data model in a way that your program can never reach an invalid state (mostly thanks to the absence of null or similar and the conciseness of enum variants). Nowadays when prototyping something I usually go to Rust first because I know that if there's a lib to do what I want it'll 9 times out of 10 (if not more) have standardized, easy to navigate documentation and the auto-completions brought about by the strict type system will guide me through the process. I do agree with the OP on that it takes quite a bit of time to learn and even more to become actually proficient in it (not even mastering it, just being able to "realistically" pick Rust for a time-sensitive project); I wouldn't ever recommend it to someone as a first programming language.
@FalcoGer
@FalcoGer Жыл бұрын
Your constructor and destructor for class Bob should be Bob and ~Bob, and not Foo and ~Foo. If you allocate an array with new, you need to use delete[] to clean that up, not just delete. In your rust code, you refer to bob when you variables are named n and b. Maybe you should get an IDE that highlights errors for you. Vim is great and all, just use syntastic or some other plugin to do that for you. Bare pointers are fine so long as it's simple and easy and there is no chance of accessing memory after it has been freed or it being very unlikely that you forget something. You should just use smart pointers instead otherwise. Unfortunately something that starts out simple can quickly grow in complexity and if you are not careful designing your API to your bob instances, someone might pull a pointer and use it outside some scope. Instead of trying to remember to allocate and clean up in two different spaces, you should just let the smart pointers handle that for you. They are well optimized. They do of course have their own drawbacks like cyclic dependencies that need to be watched out for, but generally they are the better choice. In your Bob example, a unique pointer would simply not work as you can't copy it without handing over ownership, and a shared pointer would work just fine, although you still wouldn't want to just return it like that as n probably makes no sense without bob. A weak pointer is probably the right choice here. If you want a fair comparison, then bob in c++ would also hold onto a high level structure, like std::vector, instead of a bare int[].
@oracleoftroy
@oracleoftroy Жыл бұрын
Err, no, an array of int would be represented by int*. int *x = new int; // fine int *y = new int[5]; // also fine delete x; // correct delete for single item delete [] y; // correct delete for array int ** would be an array of array of ints or a way to pass an array by reference in a C-style function so that you could (re)allocate it. But you are right about the rest, std::vector is almost always preferred if you need a dynamic array, or std::array if you don't.
@FalcoGer
@FalcoGer Жыл бұрын
@@oracleoftroy fixed it. you are correct.
@irlshrek
@irlshrek Жыл бұрын
awesome video! there are so many interesting things in rust! hopefully we get more Rust content
@Speglritz
@Speglritz Жыл бұрын
Great video. One remark would be to try compiling your examples next time. I think people unused to these languages could become confused when the code isn't accurate.
@Firepipproductions
@Firepipproductions Жыл бұрын
6:32. RAII doesn't put allocation/deallocation as work on the programmer. The programmer can use STL containers and pretty much never use the keyword new. It is called rule of 0 and is the core essence of modern C++.
@spark_coder
@spark_coder 8 ай бұрын
This is a very thorough explanation... thank you for that... But I must point out that at 5:45 inside the cpp program, within the destructor, the use of the delete keyword (delete this->n) in order to deallocate the array is wrong since it only removes the first element as the array is technically a pointer, therefore you would have to use the delete[] keyword (delete[] this->n) or loop through and delete each element. Thank you for this wonderful video ❤
@user-xs2op2iy3w
@user-xs2op2iy3w Жыл бұрын
You absolutely wrong when tell about C++. C++ already has RAII classes in STL, and in most cases you do no need to handcraft memory management. Also, resources are not only the memory, as other commentators mentioned, it might be any thing what you get from OS, like: window handles etc. The key difference in C++ and Rust is move by default in rust, and borrowing.
@zamf
@zamf Жыл бұрын
What wasn't mentioned is that the C++'s standard library is build around RAII and the notion of moving data around, so the concept is not new for Rust. Rust just enforces it by the compiler, while C++ lets you use RAII as well as unsafe resource management.
@TheJaguar1983
@TheJaguar1983 Жыл бұрын
Rust programmers tend to not know that because they're too busy running down other languages' flaws
@philosophyze
@philosophyze Жыл бұрын
I've been learning Rust this last year. Love it.
@oussamawahbi4976
@oussamawahbi4976 7 ай бұрын
rust newbie here, this is possibly the best introductory explanation to the rust borrow checker i saw on the internet
@cthree87
@cthree87 Жыл бұрын
Nice to see y'all covering Rust
@Amejonah
@Amejonah Жыл бұрын
2:37 This is NOT the same as in other languages. Val in Kotlin, final in Java, etc. makes the variable itself not reassignable not immutable. final var person = Person(19); person.setAge(20); does mutate the variable even if it has final. In Rust, however, you cannot* mutate the variable at all (as for age_set(u16) you would need a mutable reference). (* ignoring concepts like internal mutability using RefCell (assures the 1 mut xor n imut rule at runtime instead of compile time), unsafe and such)
@timokreuzer1820
@timokreuzer1820 Жыл бұрын
So Bob has a constructor called Foo? And the scalar delete operator is used in the destructor to delete the array allocated with operatot new[]? And b gets automagically renamed to bob in Rust? I guess we are dealing with a computer scientist here.
@TheJaguar1983
@TheJaguar1983 Жыл бұрын
Nah, just your average Rust evangelist.😝
@shahinza
@shahinza 7 ай бұрын
Thank you for sharing this excellent video! I truly appreciate the effort put in by education professionals like you to create such valuable content.
@vadumsenkiv8773
@vadumsenkiv8773 Жыл бұрын
So, in the C++ sample you use raw pointers and manual memory management, which is not recommend in modern C++, and you could use std::vector and return it by copy, move or const reference then you'll get the same behavior as in Rust or whatever you can want 🤷 And don't forget about references in C++ too. However, I agree that more control that C++ gives to developer requires a lot more responsibility.
@taufiqulalam2035
@taufiqulalam2035 Жыл бұрын
The C++ code is wrong in the video. First off, the constructor name. And also, in C++ if you allocate an array you gotta use delete []. The concepts were explained somewhat vaguely. I recommend anyone trying to learn this, trying to the same stuff you do in C++ just write in Rust, and the compiler will automatically guide you towards the right way to do things. In C++, it will just let you do that stuff, no problem.
@ToadalChaos
@ToadalChaos Жыл бұрын
So long as a mistake can be made, it will be made eventually. To me that's one of the greatest strengths of Rust. It prevents you from making common mistakes by being opinionated enough in it's design.
@raulwolters2380
@raulwolters2380 Жыл бұрын
The "many read-only or one read/write reference" rule is also part of the dangling pointer protection. Imagine you have a Vector with a bunch of elements, and you take a reference to one of those elements. Suppose you were to now extend the vector. In that case, you might exceed the allocated capacity, causing the whole thing to be moved to another place in memory -> your reference to the original vec (which has now been deallocated) is now invalid. Besides that, not allowing two mutable references also prevents data races, which are considered unsound in rust. It might also be worth mentioning that memory leaks are not considered unsafe or unsound in rust and are totally possible with safe rust(Box::leak, or having reference counted smart pointers point to each other in a loop like Rc1 -> Rc2 -> Rc1).
@JasonHise64
@JasonHise64 Жыл бұрын
The vector case you mention is critical. I’ve had bugs in a C++ program just due to passing a reference to an element on the stack along with a reference to the object containing the vector. Way farther up the callstack that vector grew and the reference on the stack got silently invalidated. Because of how complex the code had grown, going back and refactoring to eliminate this ‘unsafe borrowing’ was completely impractical, and the easiest way to fix the bug was just to create and use a new ‘paged’ container instead of a vector to ensure that growing the container would never invalidate references. If it had been written in rust from the get-go, that code would have failed to compile early on, long before so many dependencies were written on top of it!
Жыл бұрын
Cool that you made a video about Rust!
@gosnooky
@gosnooky Жыл бұрын
Immutability works much differently in Rust than in TS. In TS, when dealing with non-scalar values such as objects or arrays, a const won't allow the value itself to change (e.g. memory address), but you can still push to an array or add a property to an object. In Rust, it's an effective Object.freeze by default where you still need to declare "mut" to allow modifications to the underlying compound value. This is a very important distinction.
@heto795
@heto795 10 ай бұрын
Lack of mut in Rust is much closer to const in another language... C++. When applied directly to an object (like a variable), the meaning is basically the same in both languages (but there is a significant difference when applied to the type of a reference). Whether for the presenter's lack of C++ expertise or another reason, this video makes it look like the difference between C++ and Rust is many times greater than it actually is.
@adamd0ggg2
@adamd0ggg2 Жыл бұрын
After learning Rust, my best advice is to write it without using borrows at first. Do a lot of copying and returning new objects. It is not efficient but it trained my brain to think about the memory allocation and moving process. Then borrows felt like a natural optimization.
@bazoo513
@bazoo513 Жыл бұрын
ˇ2:45 : Well, C and Java also have construct to declare something to be a constant. All Rust does is make "constantness" the default, and one has to specify mutability ("variability") using an additional keyword. It's not like other languages are like Fortran V on Univac 1100 series under EXEC8, where even integer literals were actually mutable variables passed to subroutines by reference. Now, _that_ was a source of some really nice puzzles for novices.
@armpitpuncher
@armpitpuncher Жыл бұрын
That first example, where he was trying to demonstrate the difference between C++ and saying that you have to implement RAII yourself in C++, while Rust does it automatically, is just plain wrong. The authors of the Rust standard library had to manually implement the Vec struct, just like the authors of the vector class in the C++ standard library (which is what he should have been using in his C++ example). That's not a difference between the two languages. The stuff about borrowing is a difference, but that's not related to RAII.
@IamAbdulQadeerKhan
@IamAbdulQadeerKhan Жыл бұрын
Can you please share the NeoVIM configuration used by Ian in the video?
@pierreabbat6157
@pierreabbat6157 Жыл бұрын
C++ nitpick: you can't have a function ~Foo in a class named Bob. The destructor has to be named ~Bob, and similarly for the constructor.
@Matt23488
@Matt23488 Жыл бұрын
Yay a video on Rust!
@Ceelvain
@Ceelvain Жыл бұрын
RAII must be one of the biggest misnomer in programming. The core of the concept is not to bind resource acquisition to the initialisation of a variable. But rather to bind the resource release with the destruction of a variable.
@gehngis
@gehngis Жыл бұрын
The core concept is to bind the resource lifetime to a variable lifetime. This includes both binding the resource acquisition to the initialization of a variable and binding the resource release to the destruction of a variable. That's why languages without constructors like Rust cannot fully implement RAII as they cannot bind the resource acquisition to the initialization of a variable. The resource has to be acquired and then binded to its RAII variable, if stack unwinding happens between the resource acquisition and its binding, the resource won't be released.
@hanifarroisimukhlis5989
@hanifarroisimukhlis5989 Жыл бұрын
​@@gehngisnot really, when the stack unwounds the resource is dropped/released, unless releasing such cause further exceptions.
@gehngis
@gehngis Жыл бұрын
@@hanifarroisimukhlis5989 no stack unwinding does not cause resources to be released. It just destructs variables. If a resource isn't held by a RAII variable it won't get magically released. Releasing resources can mean anything like making a system call, sending USB data to a device or sending a network packet to a server. Rust, or any language, cannot do that on its own that why we have RAII: to make the system call/send USB data/send network packet in the destructor of a variable which holds the resource.
@Ceelvain
@Ceelvain Жыл бұрын
@@hanifarroisimukhlis5989 I think he meant if an exception occurs between (for instance) a malloc and setting the field RAII-variable. Then we would get a memory leak. Which is true, but it would be true of any RAII system. The resource allocation and the binding cannot be made in one atomic step. And my point was exactly this. We dont actually really care about the specific details of the steps to acquire a resource. What we care about is that the bulk of the code cannot leave a resource unreleased. Also, it doesn't actually matter if the variable initialisation happened miles before the resource is bound to the variable. As long as it is bound ASAP after it's been acquired in order to avoid the case mentioned above. Hence, it'd be better called DIRR. Destruction Is Resource Release. Or RRID. You know what? Let's try to popularise those names. 😆
@digama0
@digama0 Жыл бұрын
​@@Ceelvain In rust it definitely doesn't matter whether the value is bound or not to whether there is a gap in which a panic (aka exception) can cause a memory leak. There is no gap, when these things are lowered to the low level intermediate language all temporaries have bindings and drop elaboration happens at this level. All possible code paths are covered, including the panicking ones.
@danielmilyutin9914
@danielmilyutin9914 Жыл бұрын
5:40 you meant 'delete[] this->n;' in C++ there is difference between 'delete' and 'delete[]'.
@TJ-hs1qm
@TJ-hs1qm Ай бұрын
The explanation was perfectly fine for me, on point. There are millions of other channels to learn about the syntax 👍
@IMMACHARGINMYLAZOR
@IMMACHARGINMYLAZOR Жыл бұрын
More rust content I love it a lot
@real1cytv
@real1cytv Жыл бұрын
I think something that was a little left out ist that you can do most things with rusts RAII principles (except for multiple owners, so reference counting). If you want to free some memory halfway through an objects lifetime, you can give the Memory to an `Option` which does runtime checks on the variables validity, which your Object then holds onto. This then forces users of the object to consider whether or not the memory is valid at that current time. In rust you very rarely actually need `unsafe` blocks, unless you're doing something like embedded programming or unsafe magic. Also rusts reference counting doesn't actually violate the one owner principal, since the reference counted "backend" owns the original data (in implementation this isn't quite correct, there is an UnsafeCell backing all of this, but for the users purpose this doesn't matter)
@morgan0
@morgan0 Жыл бұрын
i’m curious if you could compare garbage collection and rust’s way of doing things with nim’s arc/orc, i’ve heard it doesn’t need to use atomic operations unlike other language’s arc implementations, but i’m not that familiar with how it works under the hood
@candysugar5681
@candysugar5681 Жыл бұрын
Why do you intentionally write bad code in C++ to elevate Rust? I'm sure the Rust community doesn't want you doing that.
@vectoralphaAI
@vectoralphaAI Жыл бұрын
Right. C++ solves this problem with std::unique_ptr.
@kwanarchive
@kwanarchive Жыл бұрын
The code is bad, but it's also more code than necessary. He had to go out of his way to make an issue, whereas one std::vector would have solved the problem.
@micahrufsvold
@micahrufsvold Жыл бұрын
I think you're forgetting the audience this video is for. A lot of people watching this don't know about rust, c++, or memory management, and they aren't going to be coding embedded code any time soon. He just needed to demonstrate clearly and quickly the memory management problems that Rust's ownership model is trying to solve. This isn't a sales pitch for programmers, it's educational content for laypeople.
@CamaradaArdi
@CamaradaArdi Жыл бұрын
It's really easy for a new programmer that doesn't know about smart pointers to fall for those traps. If he wanted to make that point he probably should had used C. Rust is better than C++ for other reasons so you're right, no need to write bad C++
@shadamethyst1258
@shadamethyst1258 Жыл бұрын
The point is also that you *can* write memory unsafe C++, despite following rules like RAII, whereas you can't in Rust, unless if you write "unsafe" somewhere. He could've presented an automatic code analysis tool for C++ that implements the move/borrow semantics and gotten to the same result, but rust has that tool built in and a syntax that is built around the move/borrow semantic, so why not use that instead.
@roryboyes2307
@roryboyes2307 Жыл бұрын
I don't know any rust. Isnt the ownership principle the equivalent of using std::move on a unique pointer in c++ only here it's the default pointer behavior?
@laundmo
@laundmo Жыл бұрын
ownership in rust is quite tightly linked with lifetimes, which (as far as i know?) c++ has no equivalent t
@AbelShields
@AbelShields Жыл бұрын
Rust moves are destructive moves, whereas C++ has to leave the moved-from object in a valid state even if it's not used again.
@CryZe92
@CryZe92 Жыл бұрын
The differences are: Moves are the default, deep copies (called clones) are the explicit alternative. Also moves are "destructive" where the compiler doesn't let you access the variable anymore. In C++ moves put the object into a "valid but unspecified" state, which is a little bit odd for types that don't necessarily have such a concept. Like what's a valid but moved mutex, thread, file, tcp stream, etc? For a lot of types there's an equivalent of a null value, but for those that I mentioned the classes need to do some special "bool is_moved" or so and probably throw an exception on all the methods? It's really weird.
@BohonChina
@BohonChina Жыл бұрын
C++ unique_ptr and shared_ptr are just like Box Arc in Rust.
@Omnifarious0
@Omnifarious0 Жыл бұрын
6:21 - You have an error. You didn't use the right form of delete. You need to delete arrays differently. In this case, it probably will be just fine. Also, you keep saying "C" and then using "C++". They're different languages. Lastly, the appropriate comparison is not to bare C++ pointers. I hardly ever use those anymore in writing C++ code. The proper comparison is C++'s unique_ptr and shared_ptr. The concept of mutable and non-mutable borrowing doesn't exactly exist with those. But those are the closest equivalent to what Rust is doing.
@SoapSoapCrayon
@SoapSoapCrayon Жыл бұрын
GC is the single worst cause of headaches in my job. I'm a senior programmer who works on video games, and I mostly deal with low level optimizations. An unreal GC collect call is going to cost 125ms on a switch. This is just for a call to GC.Collect, there might not even be any garbage to collect. Yes. that's 10 frames at 60 fps spent just looking for things to free. RAII amortizes these costs so they are hit at the moment they are freed. Spreading it out.
@Guru4hire
@Guru4hire Жыл бұрын
Wouldn't you just use a unique_ptr in the c++ example and do essentially all the same thing?
@CryZe92
@CryZe92 Жыл бұрын
unique_ptr is called unique for a reason. He would've had to create a (deep and expensive) copy of the vector to resolve the problem if he used unique_ptr (or vector). The solution would've been shared_ptr, but even that has a runtime cost, whereas in Rust it would've just been a completely free borrow and no unique_ptr / shared_ptr at all.
@Guru4hire
@Guru4hire Жыл бұрын
You can create a std::unique_ptr and move it around to pass ownership or pass it by reference to allow borrowing of it. Its the point of unique_ptr. Its what it does.
@CryZe92
@CryZe92 Жыл бұрын
@@Guru4hire Yeah but that misses the point of the example in the video. The example was that Bob had ownership and got destroyed and there was a dangling reference to the numbers still. unique_ptr wouldn‘t have helped here at all, unless you would‘ve moved out the numbers, but that‘s not what he wanted to do, he wanted to destruct Bob.
@Guru4hire
@Guru4hire Жыл бұрын
I think I understand the point of disagreement now. I am saying that a unique_ptr to a class or struct bob which has a public unique_ptr to a vector of ints performs essentially the same as all the rust code examples. I would argue that the pathological get_n function (which is not in the rust example) in the c++ example would fail to compile as the unique_ptr's copy constructor is deleted. I would have liked to see how Rust handles the contrived use after free bug with the get_n function.
@dynfoxx
@dynfoxx Жыл бұрын
@@Guru4hire one other thing is that C++ unique and shared is a runtime cost where Rust is a compile time check. C++ compiles down to pointers allocations and checks where rust just compiles to pointers.
@JumpeFurby
@JumpeFurby Жыл бұрын
Am i the only one watching this, finding it super interesting every single upload yet understanding about 5% of what they tell u?
@KavorkaDesigns
@KavorkaDesigns Жыл бұрын
Hi, can you use a tripod please or set the framerate to 24-30FPS(after recording) the high-framerate causing motion issues for me, an is why I don't watch many new shows/movies. It may also be caused slightly by the auto-focusing(type)
@novasurfer
@novasurfer Жыл бұрын
Okay, but it's not C++. No one writing programs like that in real life. There are tools which will help you to find different kinds of errors. Clang-tidy, Valgrind, PVS Studio, compiler flags like `-fsanitize=address`, maybe something for MSVC from Microsoft. Clang-tidy, can analyze code in real time, it's easy to use, and built in in CLion IDE, can be easy installed in Vim/Emacs with a help of LSP and clang tools. And of course there are unique pointers and move-semantics since 2011. Rust is cool, but C++ does not stand still.
@SqueakyNeb
@SqueakyNeb Жыл бұрын
Writing C-with-classes and calling it C++ (in that you didn't use std::vector, which is the proper approach to this code) is a bit of a hatchet job. What Rust has "built into the language" is literally right there in C++ just the same. I know examples are usually contrived but like damn dude.
@MrMediator24
@MrMediator24 Жыл бұрын
Waited for a quite a while to hear "Rust isn't a niche language". Also it has name for it's memory management system - OBRM (Object Based Resource Management)
@badassopenpolling
@badassopenpolling Жыл бұрын
Class name is Bob and constructor/destructor name is Foo. This is something new added to C++ by Ian !!!
@dripcaraybbx
@dripcaraybbx 7 ай бұрын
You had me at "It definitely wants to borrow from..."
@starlino
@starlino Жыл бұрын
C++ arrays should be deleted with `delete[]` operator @ 6:04 , this is because over-allocation or an associative array technique is used to hold the number of elements in array, so you need to hint the compiler to de-allocate the latter too.
@rohankandi9900
@rohankandi9900 Жыл бұрын
9:20 I would actually say the inverse here: at best the program crashes, at worst it gets some garbage. In my experience, debugging with garbage data has been much more hellish than immediately getting a seg fault and knowing the exact location of the problem.
@miltiadiskoutsokeras9189
@miltiadiskoutsokeras9189 Жыл бұрын
In C++ the constructor/destructor are named after the class. The Rust example seems not equivalent to the C++ one.
@Darth_Bateman
@Darth_Bateman Жыл бұрын
We can use this in our stack when implementing javascript webapps or is that not even necessary?
@victorolvera6482
@victorolvera6482 2 ай бұрын
Question: keeping track of ownership, is that done at runtime or compile time? At runtime, if every variable maintains an owner, is like extra overhead in memory at least and some speed overhead also. I am imagining a list of a thousand items and every item has ten or so variables and every variable maintains and owner. Say the cost of keeping track of owners is 4 bytes per variable. That list has 40KB of overhead just keeping track of owners.
@victorolvera6482
@victorolvera6482 2 ай бұрын
I do like the idea of three different assignment operators := that is the pascal assignment operator which defaults to copy of data (for small primitives) With strings it just copies the pointer not what its pointing to. :t= that is a transfer of ownership :c= that is a copy of data (with strings or records it makes a complete copy of the string) :a= that is making an alias identifier.
@dynfoxx
@dynfoxx Ай бұрын
It's done at compile time. If you wish you can do runtime checking of ownership using std(or your own) data structures, think mutex.
@Rick.Fleischer
@Rick.Fleischer Жыл бұрын
In C++, aren't constructors and destructors required to have the same name as the class?
@andrycraft69
@andrycraft69 Жыл бұрын
Completely unrelated question: why the numbers to the left of the code in the compiler are like that?
@mina86
@mina86 Жыл бұрын
The one to the left is line number, the one to the right is distance from the current line. This lets you easily execute editor commands such us ‘go up N lines’ or ‘delete next N lines’.
@andrycraft69
@andrycraft69 Жыл бұрын
@@mina86 Oh ok, that makes sense
@pheww81
@pheww81 Жыл бұрын
if you do a new[] please do a delete[]. Even in a so simple example bug has creep in. Furthers proof that most programmers should not write this kind of code themself.
@toby9999
@toby9999 Жыл бұрын
It's pretty basic stuff that any half decent programmer should get right. It bugs me when people blame such things on the language. Like blaming a car for driving the wrong way down a one-way street.
@razt3757
@razt3757 Жыл бұрын
You should also take a look at Zig.
@awwastor
@awwastor Жыл бұрын
Rust doesn’t actually prevent memory leaks. It is fully possible to leak memory in safe rust, although a little harder. This is demonstrated by std::mem::forget, which was at one point unsafe, but after a while it became clear that preventing memory leaks entirely was unpractical in a language like rust, due to e.g. reference counting cycles or deadlocks or tons of different things
@benmeuker4921
@benmeuker4921 Жыл бұрын
5:50 Shouldn't it be delete[] this->n; missing the array.
@Gorzoid
@Gorzoid Жыл бұрын
6:00 this is Undefined Behavior btw, you are not allowed to call delete on a pointer allocated using new[] Correct way to free it would be delete[] this->n;
@roz1
@roz1 Жыл бұрын
I spotted a mistake in his code. The constructor and destructor should have the same name as the class name. Here name of class is Bob and you named the constructor and destructor as Foo
@charlesnathansmith
@charlesnathansmith 9 ай бұрын
Is there some particular reason why Rust couldn't just use C syntax with some extra keywords? It's like they went through and needlessly changed the format of every single thing.
@happygofishing
@happygofishing 9 ай бұрын
because rust is inspired by pretentious functional programming fans, that prefer impossible to debug syntax.
@siggimund
@siggimund 10 ай бұрын
So, as a programming language and ferry enthusiast, was this interview recorded on the Dover/Calais or Dover/Dunkirk ferry connection? Hope I'll get through it without getting too seasick. 😁. Nah, sorry, that was a bikeshed comment. Very interesting and informative content actually👍
@jerryjiggler
@jerryjiggler Жыл бұрын
how does it handle memory shared between different threads? Just use a ref counter? unsafe block with fine grained control? Anything to make either of these easier?
@jocketf3083
@jocketf3083 Жыл бұрын
Generally reference counters in combination with Mutex or RwLock. These encapsulate the value and return a wrapped (Guard) reference when you call lock(). The lock is automatically released when the Guard goes out of scope. Channels help with passing data between threads. Rust also tracks what's thread safe and what isn't via the Send and Sync marker traits. Rayon is a nice library where you don't have to deal with that if you just want parallelism for iterators.
@rretro2042
@rretro2042 4 күн бұрын
Would using vectors instead of raw arrays in c++ help mitigate the memory leak issue a little more?
@siggimund
@siggimund 10 ай бұрын
Hmm? What's the difference between const& in c++ and the borrow "thing" in Rust apart from being more explicit in C++, as where in Rust you have two/several places to signal to the compiler that this reference can't be modified?
@dynfoxx
@dynfoxx 10 ай бұрын
Rust & and C++ const & are similar. The biggest difference is lifetimes and borrowing. In Rust we get guarantees we don't in C++. Rust & is non-null, aligned, and guaranteed to be pointing at active memory. It is also guarantees not to have any mutable references also pointing to that data. Rust & can also express lifetimes &'a or &'a static which can be helpful. Another notable difference is that Rust has niches meaning unlike c++ &T is the same size as Option . & can also express thread safety(no data races checked at compile time) unlike C++ &. There are probably a few other things but hopefully that makes sense. Any other questions?
@KohuGaly
@KohuGaly 9 ай бұрын
Rust references carry lifetime information. This means, that the compiler can determine where the reference is valid where it isn't. For example, consider a "get" function that receives read-only reference to a hashmap, read only reference to key and returns read-only reference to a corresponding value in the hashmap. The key reference was only used for lookup. It's irrelevant after the function returns. But the output is derived from the hashmap reference - it references the same thing. There's no way to express this relationship in directly in function signature in C++. You either have to document it or look at the source code to figure it out. In Rust, the references have lifetimes, which are part of the function signature. You can express that the output references the same thing as the hashmap reference by giving them the same lifetime parameter, and express that the key is unrelated by giving it a second lifetime parameter. the syntax looks like this: fn get(map: &'a Hashmap, key: &'b Key) -> &'a Value {...} Now the compiler is able to deduce that this is OK: let value = get(&map,&key); drop(key); use(value); and that this is not OK: let value = get(&map,&key); drop(map); use(value); // compiler detects use after free error The compiler doesn't even need to see the implementation to deduce this. It can deduce it purely from the function signature. Similarly, at the function definition, it is able to check that the implementation matches what the signature is claiming. Note, that this is just one example of the sorts of patterns that lifetimes let you express.
@31redorange08
@31redorange08 Жыл бұрын
9:17 Isn't it the other way around? The crash being the best case because continuing with garbage is very dangerous?
@smurfyday
@smurfyday Жыл бұрын
Can someone explain why multiple borrowers of the same data wouldn't be a problem for dangling pointers? If you delete the data, won't references to it become dangerous? Or is the original function still the owner so only it can do the deletion? But how would it know that all the borrowers are done?
@negativeseven
@negativeseven Жыл бұрын
Borrowers can't outlive the owner. This is enforced at compile time.
@coder436
@coder436 Жыл бұрын
1:14 does it need an immutable reference or a mutable reference?
@sumansaha295
@sumansaha295 Жыл бұрын
I like rust but there are no large well known projects with it yet which makes me a bit anxious about the practical applicability of the language given how strict it is with everything.
@dynfoxx
@dynfoxx Жыл бұрын
While Rust does not have any big user facing killer apps, you are or most likely will be using it within the next year. Firefox, cloudflare and Android already uses it. Microsoft, Apple and Google have picked it up(may already use it). Linux and Chrome have are adding support for Rust. While Rust is still getting features and is not perfect for every project there is no doubt that it is a viable programming language.
@Kuratius
@Kuratius Жыл бұрын
​​​@@dynfoxx Firefox/Mozilla are the ones that made rust and they ultimately decided against using it for the thing they invested into it for: servo. There are still some components of Firefox in Rust, but the most performance critical component isn't and probably never will be.
@x1expert1x
@x1expert1x Жыл бұрын
19:49 where are you getting bob.n from? The value of bob is held in variable name b, not bob. is this just a typo you didn't notice?
@sumedhkulkarni5346
@sumedhkulkarni5346 Жыл бұрын
How does borrowing works in multi threading? Can multiple concurrent functions borrow a variable at same time?
@dynfoxx
@dynfoxx Жыл бұрын
The rules don't change for threading(other then send and sync) If you use scoped threads it's easy to see. You can have either moved ownership, multiple immutable references or one mutable one.
@HaouasLeDocteur
@HaouasLeDocteur Жыл бұрын
8:40 why use ``new``? That kinda goes against the whole RAII thing. Should have had Bob as an automatic object on the stack so that when you leave that scope its destructor is called without you needing to ``delete`` it. In that case, even the dangling pointer may have been avoided.
@S3Kglitches
@S3Kglitches Жыл бұрын
RAII is not only malloc and free. RAII is also about file streams, memory streams, file handles, network sockets, db connections.
@frankhart2018
@frankhart2018 Жыл бұрын
Thanks for the video. It would be nicer, if there were some program runs as well, like the garbage collection video :)
@AntonAdelson
@AntonAdelson Жыл бұрын
This is something I asked before but never got an answer. How does Rust handle asynchronous programming? I mean cases where you create an object but you must keep it in memory AFTER its scope runs out because it'll be used by the async function when it's ready???
@sumansaha295
@sumansaha295 Жыл бұрын
I am not completely sure but an async function is converted into a finite state machine that is then handled by an async runtime like tokio. So the runtime does all the memory management. But it's very low overhead unlike garbage collectors.
@oracleoftroy
@oracleoftroy Жыл бұрын
Not a Rust programmer (as a C++ guy I've been keeping my eye on it and messed with it in small programs), so I might miss the finer details, but you either move the memory into the async function so that the owner (and thus the responsibility of releasing it) is transferred, or if multiple functions need ownership, you use a reference counted shared pointer (Rc or Arc, I forget which one is appropriate for multi-threading). Or you redesign your algorithm to not have this situation in the first place, as any sort of sharing tends to be bad for concurrency in general.
@OrbitalCookie
@OrbitalCookie Жыл бұрын
From simplest to complex: pass object when creating a thread, get the result when the thread finishes; wrap data in Mutex to access it from multiple threads; use channels to send data between threads; use async/await to run many things concurrently on an executor that handles threading (this is mostly used for I/O tasks).
@OrbitalCookie
@OrbitalCookie Жыл бұрын
Forgot the last one: write your own mechanism like channels using unsafe rust and raw pointers that has a safe rust api surface and can't be misused. Some say it's very advanced and not for newbies, but if you want freedom to shoot yourself in the foot, rust rivals and surpasses C++ in this area.
@AntonAdelson
@AntonAdelson Жыл бұрын
@@OrbitalCookie Wait, what? So there are unsafe raw pointers? Is it just syntaxis sugar to use them or something more complicated?
@JorgetePanete
@JorgetePanete Жыл бұрын
I hope they add some touch of dependent types beyond a number in a type
@wiserdivisor
@wiserdivisor Жыл бұрын
This guy knows neither C++ nor Rust.
@__-dy9gv
@__-dy9gv Жыл бұрын
the problem with garbage collection is much more then its cost in resources. It doesn't solve the general problem of resource management and in/out operations. because with garbage collection the time and ordering of destruction is not unspecified. so any resource that has side-effects in its destructor is usually not safe to run during destruction. RAII and rust's Drop traits solve this issue by having a per-determined ordering of destruction. so RAII is used in C++ for many many things: management of memory, lock/unlock mutexes, timing scopes, management of OS/external handles, unhandeled error detection, parser scope tracking, statistics tracking, post-condition checking......... also this video makes it sound like RAII must always be done by hand in C++ which is wrong. Most of the time libraries have the utilities with the behavior you need an you can reuse them. rust's Box should be compared with std::unique_ptr. not doing it by hand.
@RuiLopesFR
@RuiLopesFR 8 ай бұрын
Conclusion is a bit odd, "saves much complexity" - quite the opposite I find. If I'm using a program to crunch accountancy numbers and on top of that I need to keep the hurdle of managing memory, complexity explodes as I need to keep multiple contexts and semantics in my head. Especially when I'm going from RAII into unsafe into boxing... quite a nightmare - and the error messages from Rust are quite exotic/cryptic. I'd rather use garbage collection and focus on my business need, rather than fiddling with memory management at the same time.
@bradmartisius2625
@bradmartisius2625 Жыл бұрын
When you have a class Bob in C++, the constructor is named Bob(arguments) & the destructor is named ~Bob(). The code shown in the video can't compile.
@oerglwoergl
@oerglwoergl Жыл бұрын
It would be nice if the code actually compiled (C++ class Bob having constructor and destructor named Foo: no) or does what we're told it is supposed to do ( in rust Vec::new() doesn't allocate anything. It creates an empty vec - such a vec starts allocating in push).
@InShadowsLinger
@InShadowsLinger Жыл бұрын
I wish there was more info on how this is handled in asynchronous execution. I know he mentioned there is reference counting, but I wish he showed it.
@zactron1997
@zactron1997 Жыл бұрын
Async Rust is delightfully complex, but also still not quite done. Making asynchronous structure methods in a trait (aka, interfaces) is not pleasant. The way rust uses the await keyword to divide async blocks of code into a state machine (basically a large enum in Rust) is very clever.
@hanifarroisimukhlis5989
@hanifarroisimukhlis5989 Жыл бұрын
@@zactron1997 It's mostly due to how complex verifying what lifetimes is the async context. With GAT stabilized, it provides a step towards async traits.
@zactron1997
@zactron1997 Жыл бұрын
@@hanifarroisimukhlis5989 Oh yes it's a very complicated problem the language team is trying to solve. I absolutely love Rust and have started using it at work where appropriate. Rust is a living language more than any other I'm aware of right now, and in the next edition it looks like there'll be some major changes
@OrbitalCookie
@OrbitalCookie Жыл бұрын
To be fair there are much better resources than this. They even try to make sure that their examples compile.
@AU-hs6zw
@AU-hs6zw Жыл бұрын
Thank you!. It is a great video.
@maximilianoredigonda8645
@maximilianoredigonda8645 Жыл бұрын
This was awesome, please do more videos on Rust! The explanation is so clear, and I'm sure you can do the same for other more complex concepts as well!
Garbage Collection (Mark & Sweep) - Computerphile
16:22
Computerphile
Рет қаралды 231 М.
Learning Rust the wrong way - Ólafur Waage - NDC TechTown 2022
51:54
NDC Conferences
Рет қаралды 97 М.
Trágico final :(
01:00
Juan De Dios Pantoja
Рет қаралды 17 МЛН
Doom didn't kill the Amiga...Wolfenstein 3D did
16:58
Modern Vintage Gamer
Рет қаралды 92 М.
All Rust features explained
21:30
Let's Get Rusty
Рет қаралды 272 М.
Async Rust Is A Bad Language | Prime Reacts
28:46
ThePrimeTime
Рет қаралды 82 М.
How AI 'Understands' Images (CLIP) - Computerphile
18:05
Computerphile
Рет қаралды 127 М.
Rust for the impatient
10:43
No Boilerplate
Рет қаралды 637 М.
Has Generative AI Already Peaked? - Computerphile
12:48
Computerphile
Рет қаралды 417 М.
What Everyone Missed About The Linux Hack
20:24
Theo - t3․gg
Рет қаралды 271 М.
Why do developers hate Rust?
8:20
Let's Get Rusty
Рет қаралды 87 М.
Visualizing memory layout of Rust's data types
39:39
Sreekanth
Рет қаралды 7 М.
Understanding Ownership in Rust
25:31
Let's Get Rusty
Рет қаралды 233 М.