54

First, a quick disclaimer: I don't know Rust (or Go). So I'm going to focus on only things that are obvious to a programmer unfamiliar with the languages discussed in the post. I'm sure a Rust or Go expert could find additional errors, based on the accuracy of what I can verify.

Link to the blog post in question


The heap is a hierarchical data structure used to store global variables randomly

This is just...wrong. First of all, the heap isn't necessarily hierarchical—there is a wide variety of techniques used by memory allocators. They (and the source they appear to have gotten this from) seem to be conflating the data structure called a heap with the memory-management concept of the heap. Based on the phrasing in the blog post, ("The stack is a linear data structure... The heap is a hierarchical data structure..."), it's pretty clear where they got this information:

Google search result showing "Stack is a linear data structure whereas Heap is a hierarchical data structure. Stack memory will never become fragmented whereas Heap memory can become fragmented as blocks of memory are first allocated and then freed. Stack accesses local variables only while Heap allows you to access variables globally." in a featured snippet

Second, the heap stores more than global variables (it stores anything allocated off the stack, which includes the storage for any dynamically allocated objects), and it doesn't store them "randomly": it uses a memory allocator. Different allocators use different strategies, but I'm pretty sure storing things in random locations isn't one that any reasonable allocator uses. They refer to this "random process of allocating memory" again later, as well.

Local variables, functions, and methods reside on the stack...

No, functions and methods are stored in the code. Maybe they mean function/method parameters?

...and everything else resides on the heap

...except for constants, which are stored elsewhere.

When a literal is pushed onto the stack...
...
Rust handles memory efficiently by storing literals (integers, booleans, etc) on the stack

The author seems to have no idea what a literal is (it refers to writing a literal number, string, etc. in code). They're almost certainly thinking of a primitive. And primitives could also be stored in the heap, depending on how they're used.

This could be detrimental to code security if external dependencies use the unsafe keyword.

Why is this specific to external dependencies? It's just as detrimental if you do it in your own code.

Rust, with the standard library and borrow checker, would be better to use in building resource-intensive applications that need handling.

It's unclear what it means for an application to "need handling."

Rust for building applications that require low-level interaction where performance and memory safety is paramount
...
you can consider using Go for programs where memory management isn’t a big deal and you care about performance

Which one do I use when I care about performance?

Rust and Go are fairly new, powerful languages often compared in many terms including memory management.
...
Go and Rust are quite incomparable when discussing memory management

Okay, this one is a cheap shot and not actually an error. But the phrasing is awkward: are they comparable or not? They probably meant different.

Copying ownership

The code in this section does not match the output. The code uses a primitive integer, which does implement the Copy trait. The output uses a string, which does not. The text switches which one it's talking about back and forth.


Finally, the article contains numerous images of text. The author and editors should strongly consider reading Why should I not upload images of code/data/errors when asking a question? Try shrinking your browser window down like you were on a mobile device and try to read them. And naturally, they all have blank alt text, as is standard for the blog, so they're completely inaccessible to users with screen readers.

7
  • 2
    While I agree, what you suggest to do? Sounds like fixing all the issues isn't possible without re-writing everything, so maybe better just take it down, for now? Commented Jul 15, 2022 at 7:21
  • 11
    @ShadowTheKidWizard I don't know what the best approach is. I don't know if the blog team has access to experts that could rewrite it correctly, but that would certainly be ideal: it's an interesting subject that I would find interesting to read an accurate blog post about. I was disappointed that this was so riddled with errors that I wasn't confident in anything I could have learned from it. It at least needs to be looked over by someone familiar with Rust (and probably Go).
    – Ryan M
    Commented Jul 15, 2022 at 7:30
  • 25
    More generally, I'd like to see the blog team find a way to check these posts for these sorts of obvious technical errors before they go up. Consulting someone familiar with the subject (the company employs many software engineers, surely one of them could review it). It's a bad look for the blog of a site that is in many ways the go-to reference for programmers to find reliable information...and indeed, as evidenced by some of the links I included here, the correct information is available on Stack Overflow itself.
    – Ryan M
    Commented Jul 15, 2022 at 7:30
  • 2
    @RyanM I thought the go-to reference for programmers was MDN? Maybe that’s just because I have been reading so much about web development. Speaking of Mozilla, I just read a nice post on a Mozilla blog about why writing safe code in C is so hard, with reference to a recent bugfix (which did nothing more than change a function argument from signed to unsigned). It was written by the same person who reported and fixed the bug (that is, by someone who knew what they were talking about). Why can’t SE do that? Commented Jul 15, 2022 at 10:52
  • 14
  • 15
    @HenryEcker Another one: Almost none of the JSON in the blog about JSON is JSON - it baffles me that so many blog posts contains so much incorrect information. Stack Overflow contains lots of canonical, correct and accurate information about all those subjects, and I wonder if the people who post check that before posting
    – hkotsubo
    Commented Jul 15, 2022 at 13:25
  • 1
    I had a user-style applied on SO precisely to hide blog posts from the sidebar because I did not care about them... I have removed it some time ago because it's just too fun to play whack-a-mole spotting the errors in these "technical" articles. Commented Jul 20, 2022 at 0:04

2 Answers 2

27

As always, I appreciate the thorough comments on this one. It looks like this post is pretty badly incorrect, so I've taken it offline for now. The amount of work that it'll take to get this to an accurate state is not something I can prioritize right now, so instead of having something potentially harmful up while I make some edits, it's going away.

I'm also looking to change who I accept pitches from. I'll be accepting less coming in and reaching out more. For incoming pitches, I'm considering requiring SO accounts with a proven track record -- I would appreciate your thoughts on whether that's a good idea.

Stack Overflow has a global audience and is visited by users of all skill levels. We want our blog to represent the community in all its forms. That said, we see the need to course correct here. As always, if you folks who are involved enough to provide this level of detailed feedback want to write something, email me at [email protected]. Or if you think someone would make a good contributor, send them along to me.

4
  • 3
    Thanks for adressing this Ryan, does that mean this question can be marked [status-completed]?
    – Luuklag
    Commented Jul 22, 2022 at 5:29
  • @Luuklag I don't think so, when it will be back up with the corrections it would be completed. Commented Jul 22, 2022 at 14:04
  • 1
    @ShadowTheKidWizard: I think it's safe to mark it as completed for now, since I'm guessing there's always a possibility it may not get republished. I'll retag this post as [status-completed] now.
    – V2Blast Staff
    Commented Jul 22, 2022 at 18:30
  • 8
    You could leverage the community before it goes up on the blog. Find those "proven track record" folks for the topic, randomly select a few, and ask them review the post for technical issues in a private Teams instance or something. I don't know how the process works exactly, but SE has a whole mess of experts already volunteering their time and an entire system designed to allow a group to rank and improve technical knowledge content. It's not as hard to find time to review as it is to write something from scratch.
    – ColleenV
    Commented Jul 22, 2022 at 19:35
41

I am a Rust subject matter expert, and I would like to further substantiate the erratic nature of the blog with a few more issues I encountered.

The computer memory allocated to running programs is divided into the stack and the heap.

[...]

Rust handles memory efficiently by storing literals (integers, booleans, etc) on the stack.

Even if we discard the conflation between a literal and a primitive piece of memory, it seems to disregard that a process contains more memory segments than just stack and heap, and that something like the string below could reside in a static, read-only memory segment.

static DERP: &str = "Imma static string hurr durr";

In any case, the Rust Programming Language book provides more solid definitions of stack and heap.

If a variable is assigned to a new owner, then the original value gets dropped, as it would now have two owners.

That is inaccurate. The compiler does have the concept of moving a resource, so a typical assignment would not "drop" the original value. At best, it would invalidate that variable for further use.

let x = String::from("wat");
let y = x; // moved, no memory allocation or freeing takes place

It is not that the author is oblivious of the concept of moving a resource either, as that is further explained some sections later. It is possible that another conflation took place between variable bindings and values.

To allow programs to reuse code, Rust offers the concept of borrowing, which is similar to pointers.

OK, I may be picky here, but saying that "borrowing is similar to pointers" is a severe undermining of the borrowing system. If the target audience intended was the overall developer base, portraying borrowing as "creating references with extra guarantees", or even just as "similar to references", would have been much better.

fn list_vectors(vec: &Vec<i32>) {
    for element in vec {
        println!("{}", element);
    }
}

This signature does not follow idiomatic guidelines for passing sequential data to a function, something which anyone sufficiently experienced in Rust would know. The signature below is simpler and works for even more types of inputs.

fn list_vectors(vec: &[i32]) {
    for element in vec {
        println!("{}", element);
    }
}

(not to mention that list_vectors is a poor name for printing each element of a single vector)

The subsequent example of mutable borrowing:

fn add_element(vec: &mut Vec<i32>) -> &mut Vec<i32> {
    vec.push(4);

    return vec
}

...just makes no sense at all! It does not make it clear that a mutable borrow already "returns" the value back to the owner, even if you do not return it again. It passes along a mutable reference to the caller when there is hardly a need for that.

A proper, idiomatic way of writing this function and explaining mutable borrowing would be:

fn add_element(vec: &mut Vec<i32>) {
    vec.push(4);
}

And with this you would be able to write this:

let mut my_vec = vec![1,2,3];
add_element(&mut my_vec);
println!("my vec: {:?}", my_vec); // prints [1, 2, 3, 4]

Copying duplicates values by copying bits.

Has the post been subjected to any kind of proof-reading?

If everything was perfect with Rust’s borrow checker, other systems programming languages might switch or offer releases with an implementation of a borrow checker. On the subject of memory management, it’s a trade-off between user experience and convenience.

These sentences leave the impression that borrow checking is a feature that a language development team could add on top of most systems programming languages if they just wanted to, which is very misguided. Even the latest efforts in C++ to better diagnose resource misuses (namely the Lifetime profile specification) cannot go as deep as Rust goes, because that would have required a non-backwards-compatible overhaul of the type system.

And this section continues with other phrases which are either vague, unclear, or just downright misleading.

As program size grows, it may be difficult to self-ensure the ownership rules, and making changes may be expensive.

I would be surprised if there was a strong correlation between code size and difficulty in satisfying the borrow checker. These difficulties emerge as you try to express more complex data structures and algorithms, not exactly when the program size increases. Further down the same section, it becomes clear that the author meant something else when saying "as program size grows":

Many developers, from beginners to experts, get ownership errors from the borrow checker, with more errors coming from implementing complex data structures and algorithms in Rust.

"Expensive" could also mean a lot of things, but most of the time the only potential cost is in compilation times, unless the recourse was to clone many values around or encapsulate values in reference-counted primitives. Maybe I'd let it pass.

While the Rust compiler prevents mistakes like dangling references by performing checks, Rust also provides an unsafe keyword for developers to leave the block unchecked.

This is one of the biggest misleading sentences about Rust that you can find out there, and it's appalling that Stack Overflow is contributing to this misconception. Let's be clear here: The unsafe keyword does not disable nor relax the borrow checker. Rather, it lets the developer do things that the compiler cannot ensure that are safe.

It may seem subtle, but it makes a huge difference. Wrapping a piece of code around unsafe does not suddenly make it ignore borrow checking. Rather, it lets the developer do, among other things, the dereferencing of raw pointers. As raw pointers are more akin to pointers in C, they hold no lifetime information, nor do they guarantee that they actually point to something valid.

This could be detrimental to code security if external dependencies use the unsafe keyword.

I too find this phrase confusing. What I can say is that each unsafe block could indeed be an open door to memory-related vulnerabilities. When projects depend on unsafe, developers are advised to carefully document each occurrence explaining how the necessary conditions for safety are fulfilled. Libraries depending on unsafe may typically include other forms of testing to detect misuses (such as running tests on an interpreter, or with memory sanitizers). Still, most projects do not need unsafe, and its use is preferably kept reserved to places where it is absolutely needed. My biggest Rust project, comprising 16 crates over 30k lines of code, uses no unsafe blocks directly.

Not sure if this changes the overall interpretation of the sentence. I still consider the poor wording of the previous sentence about unsafe a much greater peeve.


All of this to say that the folks at Stack Exchange Inc should probably take better care when looking for writers for their blog, as well as when reviewing the content for both technical accuracy and readability. We can't downvote these blog posts, which makes things worse.

In this case, I wonder if you had just considered inviting Jake Goulding for another blog post on the subject, whose knowledge on the topic is quite well proven.

3
  • 2
    It seems that a number of the problems stem from their misuse of terminology. They appear to conflate variables and their contents, using the term "variable" for both. In "The variable initial is cloned in the declaration of later, and the two variables reside on the heap. If this were borrowing, the two variables would reference the same object; however, in this case, the two variables are new declarations on the heap and occupy separate memory addresses.", it refers to, respectively, the object, the objects, the variables, and...well, "declarations on the heap" doesn't really make sense.
    – Ryan M
    Commented Jul 15, 2022 at 22:55
  • 2
    That is one possibility, @RyanM. On the other hand, that alone does not justify the utterly imprecise presentation of unsafe.
    – E_net4
    Commented Jul 16, 2022 at 8:37
  • 1
    Yeah, it's definitely not the only problem.
    – Ryan M
    Commented Jul 16, 2022 at 12:32

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .