TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

Why writing a linked list in safe Rust is so damned hard

202 pointsby michael_fineabout 7 years ago

18 comments

ekiddabout 7 years ago
Yeah, a doubly-linked list is basically the worst possible choice for your first program in Rust. This is because Rust likes all of your memory to have one clear owner. And this means that cyclic data structures are unusually difficult compared to almost any other first program you might choose.<p>But if you really want to know how to do it, there&#x27;s a really good tutorial on the subject titled &quot;Learning Rust With Entirely Too Many Linked Lists&quot;: <a href="http:&#x2F;&#x2F;cglab.ca&#x2F;~abeinges&#x2F;blah&#x2F;too-many-lists&#x2F;book&#x2F;" rel="nofollow">http:&#x2F;&#x2F;cglab.ca&#x2F;~abeinges&#x2F;blah&#x2F;too-many-lists&#x2F;book&#x2F;</a><p>This will walk you through multiple different kinds of linked lists, and show you how to implement each in Rust. Along the way, you&#x27;ll learn more about Rust&#x27;s ownership system than most working Rust programmers generally need to know.<p>Personally, I&#x27;ve written quite a bit of production Rust code, and I&#x27;ve done so without ever touching &#x27;unsafe&#x27; or needing a linked list. If I really did need a linked list, I&#x27;d either grab a good one off crates.io, or just knock out a quick one using `unsafe` and raw pointers. I mean, Rust can do basically anything C does if I ask nicely. It&#x27;s just that if I choose to write &quot;C in Rust&quot;, then I get about same safety guarantees that C offers.
评论 #16443867 未加载
评论 #16446052 未加载
评论 #16445726 未加载
评论 #16448065 未加载
madezabout 7 years ago
That Rusts compiler fights against intuitive doubly linked lists is reasonable, because they wouldn&#x27;t work when working in parallel on the list, while Rust by default also ensures safety doing that.<p>Having that in mind makes it easier for me to come up with ways how to appease the compiler. What measures would you take to write a thread-safe doubly linked list in C? Would you make it entirely exclusive and blocking? Well, then you might want let one &quot;list&quot; structure own all nodes. Would you want to allow parallel execution of operations on the list? Well, then break the ownership of the nodes up into smaller parts that you can hand out in parallel when they don&#x27;t affect each other. What granularity of allowed and prepared-for parallelism gives the best performance depends on the use-case.
评论 #16443715 未加载
评论 #16444685 未加载
评论 #16443693 未加载
Animatsabout 7 years ago
I&#x27;ve previously discussed on HN how Rust could support backpointers safely.[1] The idea is to have a &quot;backpointer&quot; attribute, with some additional checking. Backpointers are non-owning pointers locked in an invariant relationship with an owning pointer.<p>You need backpointers not only for doubly linked lists, but for some tree-type data structures. The backpointer invariant is easy to check at run-time, and it&#x27;s often possible to eliminate that check at compile time. With this feature, few if any tree-type data structures need &quot;unsafe&quot;. Tree update code is error-prone; you need all the help you can get there.<p>The other basic thing you can&#x27;t express safely in Rust is a partially initialized array. If you had syntax for &quot;This array is initialized up to element N&quot;, with suitable checking, &quot;vec&quot; could be written safely.<p>Rust is pretty close on this. Those are the two main gaps in the safety system. Calling external non-Rust code is a separate problem, one which hopefully will decline as more low-level libraries are rewritten in Rust.<p>[1] <a href="https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=14303858" rel="nofollow">https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=14303858</a>
评论 #16446658 未加载
评论 #16443981 未加载
vvandersabout 7 years ago
Option #3(indexed tree) looks non-ideal but it actually has some really cool properties if you do it right.<p>1. If you know traversal order you can get <i>really</i> great cache coherency. We used to do this all the time with animation DAGs and the like in gamedev.<p>2. If everything is an &quot;offset&quot;&#x2F;index instead of a pointer you can do things like in-place loading where creating something is just a single read() call. No constructors or annoying allocations to slow down loading. If you want to take this even further you can mmap() the entire file on disk and use massive(500mb+) files without using much actual memory overhead through letting the kernel page it in&#x2F;out for you.
评论 #16443620 未加载
评论 #16445736 未加载
squiguy7about 7 years ago
There is some good discussion on &#x2F;r&#x2F;rust [0] as well. I&#x27;m not trying to invalidate the author&#x27;s post but rather share some more insight.<p>[0]: <a href="https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;rust&#x2F;comments&#x2F;7z7p5m&#x2F;why_writing_a_linked_list_in_rust_is_basically&#x2F;" rel="nofollow">https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;rust&#x2F;comments&#x2F;7z7p5m&#x2F;why_writing_a_...</a>
评论 #16443076 未加载
zerosanityabout 7 years ago
Just a friendly reminder the you can get the Programming Rust book for only $15 along with a bunch of other good books for 3 more days at the Humble Bundle Functional Programming Bundle. I&#x27;ve been working my way through it and learned a lot so far about Rust.
kovrikabout 7 years ago
I&#x27;ve struggled with Rust just a couple of times, nothing serious, so I&#x27;m not an experienced Rustacean by any means.<p>Question:<p>Ownership system obviously imposes some limitations, but gives safety in return.<p>Are there any data-structures or algorithms or something that you simply cannot implement in Rust without using unsafe?
评论 #16443116 未加载
评论 #16443194 未加载
评论 #16444155 未加载
评论 #16443162 未加载
评论 #16445993 未加载
评论 #16443118 未加载
评论 #16443170 未加载
mehrdadnabout 7 years ago
&gt; I find a bit of solace in the fact that implementing a data structure like this in a non-garbage collected language <i>without</i> Rust is also quite tricky<p>What? No it isn&#x27;t. The entire problem here is incorrectly assuming that &quot;A owns B&quot; implies &quot;A has a pointer to B&quot;. I don&#x27;t know if this is a Rust-imposed constraint, but it certainly isn&#x27;t a logically necessary one. Just do what C++ (and C#, etc.) do: the data structure (std::list, etc.) owns all the nodes, and the nodes merely reference each other. The nodes don&#x27;t own their siblings. It makes sense and it doesn&#x27;t get tricky.
评论 #16443446 未加载
评论 #16443120 未加载
评论 #16443617 未加载
评论 #16443041 未加载
评论 #16443109 未加载
zannyabout 7 years ago
Nobody mentioned that the Rust std has a doubly linked list in it? [1]<p>It uses shared pointers to reference other nodes in the sequence.<p>[1] <a href="https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;src&#x2F;alloc&#x2F;linked_list.rs.html#46-51" rel="nofollow">https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;src&#x2F;alloc&#x2F;linked_list.rs.html#46-5...</a>
评论 #16443878 未加载
teacpdeabout 7 years ago
I recently started to actually write some Rust code after reading about Rust here and there. The experience has been quite unique, it constantly forces me to think about the code at low level, which I find refreshing. And the compiler is truly impressive, it pinpoints me where things go wrong, and conveys the error messages in a very human-like fashion.
hcsabout 7 years ago
&gt; &#x2F;&#x2F; I actually don&#x27;t understand why the line below compiles.<p>&gt; &#x2F;&#x2F; Since `head` was moved into the box, I&#x27;m not sure why I can mutate it.<p>&gt; head.next = Some(Box::new(next));<p>I&#x27;m fairly new to Rust myself, but it&#x27;s my understanding that since it was moved into the Box, the variable &quot;head&quot; is now just considered effectively uninitialized, so you can go ahead and set its fields, or overwrite it entirely with head = Node {...}, without affecting the value that was moved into the Box.
评论 #16444450 未加载
AceJohnny2about 7 years ago
Tangentially, I&#x27;d love to see some list of &quot;what does this language make easy&quot; (C: raw memory manipulation!) and &quot;makes hard&quot; (C: memory-safe code)...<p>Does one exist for Rust?
评论 #16443689 未加载
评论 #16449460 未加载
kazinatorabout 7 years ago
&quot;safe&quot; means more than just memory safety.<p>Free from deadlocks, for one thing; who cares if no memory is misused if the show locks up.<p>Also, free from problems like thread A only traversing half the list because B removed a node in the middle which derailed A into a null pointer that looked like the list terminator (Even though no memory was misused.)
ameliusabout 7 years ago
Also interesting is to figure out how Rust deals with closures, which reference the parent scopes, and how the corresponding (cyclic) data structures are managed.<p>Does Rust eliminate the cycles by copying? (expensive, and doesn&#x27;t allow for writing)
评论 #16443691 未加载
评论 #16443092 未加载
评论 #16443094 未加载
GreaterFoolabout 7 years ago
You don&#x27;t have to go as far as doubly-linked list. Writing a simple cons-list is hard enough:<p><pre><code> enum List&lt;T&gt; { Nil, Cons(T, Box&lt;List&lt;T&gt;&gt;) } </code></pre> Imagine you&#x27;re writing `Iterator`. You have a `&amp;mut List&lt;T&gt;`. For `Nil`, you&#x27;re done. For `Cons`, you take it apart, return the `T`, deref the `Box` and move your `&amp;mut List&lt;T&gt;` to point to that value. Nothing could be easier, right?<p>Except in Rust you can&#x27;t do that! One can resort to unsafe code or use ugly and inefficient workarounds to remain in safe-land.
评论 #16444367 未加载
jokoonabout 7 years ago
I don&#x27;t understand why there is a need for linked lists. I&#x27;m reading about fast insert in the middle, but there are other ways to insert data quickly. Maybe it&#x27;s a need on hardware with specific memory management?<p>There are so many drawbacks to linked lists: cache incoherence, the use of pointers, no fast random access...<p>The single fact that rust makes it hard to implement a linked list should show that this data structure is a bad idea. Even when the C++ author is saying it, that should be enough, no?
ameliusabout 7 years ago
Firefox is written in Rust, and I suspect that their DOM implementation has backpointers (from children back to parents), for performance reasons. It might be interesting to check how they did it.
评论 #16443141 未加载
评论 #16443025 未加载
dmitrygrabout 7 years ago
<p><pre><code> struct node{ uint64_t val; struct node *next; struct node *prev; }; </code></pre> :)