• 0 Posts
  • 5 Comments
Joined 2 years ago
cake
Cake day: July 3rd, 2023

help-circle

  • I disagree with the blanket statement “C++ isn’t memory safe”. C++ provides the tools for writing memory-safe code, but it does not enforce it by default.

    This is such a weird take. C++ isn’t memory safe. The blanket statement is… true. You say as much in the second sentence.

    With C++, you retain full control over memory management and can choose the best tool for the job. You’re not boxed into a strict ownership model that may force refactoring or add extra layers of abstraction.

    You have full control in Rust too, at least to the same extent as C++. Rust isn’t memory safe either. Rust is just the opposite of C++ in the approach to safety: you opt in to being unsafe with the unsafe construct instead of being unsafe by default. They’re just different paradigms. I’d actually argue that you don’t have full control in either language unless you opt in to it, modern C++ tries very hard to abstract away memory management. You can write an entire program without a single new or malloc, which is pretty great.

    Sure, mistakes can happen, but with proper practices and modern C++ features you can achieve a level of safety that meets most needs without sacrificing the expressiveness and efficiency you might require in complex systems.

    This is just simply not true and is consistently proven incorrect every time an aspect of C++'s memory unsafety is exploited. I work in security and I still, in 2025, exploit memory corruption. The best developers money can buy still make mistakes with C and C++.

    Besides that: which conventions do you mean?

    The way you have to interact with smart pointers for example:

    #include <memory>
    
    int main(int argc, char** argv)
    {
        std::unique_ptr<int> a = std::make_unique<int>(1);
        std::unique_ptr<int> b(a.get());
    }
    

    Double free, but compiles without warning. It’s convention to not use unique_pointer’s constructor, not enforced.

    #include <iostream>
    #include <string>
    
    int main(int argc, char** argv)
    {
        const char* c;
        {
            std::string a("HelloThisIsAHeapString");
            c = a.c_str();
        }
        std::cout << c << std::endl;
    }
    

    Use after free. No compiler error or warning, it’s convention to not maintain references to C++ string data, not enforced.

    That’s all fine, whatever, but these are conventions. We’ve shot ourselves in the foot a million times and come up with our own guard rails, but the developer needs to know all of them to not make the mistake.


  • You said performance, so I responded to that. You can dislike Rust, that’s fine, but a lot of the things you’re saying aren’t correct. C++ isn’t memory safe, the person responding before showed that pretty easily. Rust doesn’t perform slower than C++, I responded to that claim. Rust provides tools to be memory safe, but the existence of unsafe I’d argue makes it also not memory safe, but at least better than C/C++. It also has tons of undefined behavior, just like those two.

    As for the personal opinion; you don’t have to like Rust. I actually have a very different view of the borrow checker and I don’t think I’ve ever “fought” it in a time when I was also doing something inherently safe. Every time I’ve had an issue with satisfying the borrow checker, which is rare, it’s been because I was doing something unsafe or interacting with C code, which Rust would argue is also unsafe. In my experience, it really eases the burden of programming actually and it makes debugging easier. It also makes design easier. As an example, I’ve been working on a very large C project recently and I ran into a bug where I was getting the wrong data printed out when I checked a value. After looking into it for like 15 minutes, I finally figured out that I had accidentally passed a stack pointer to a function that I wrote expecting a heap pointer. When the function went out of scope the data was garbage, but there was no crash and no compiler error. The borrow checker would have helpfully stopped me in my tracks there and saved that 15 minutes of debugging. The fact that it’s hard to implement your own efficient linked list or vector type has never been a problem for me really, especially not in comparison to the gains of not always having to keep ownership and lifetimes of pointers in my own head or in documentation that may go stale. I can’t express enough how helpful that is to my programming experience. C puts the burden of pointer lifetimes and ownership entirely on the developer. C++ makes that a bit better with the smart pointers at least, but those have some rules that aren’t enforced by the compiler but instead by convention.

    Basically I find the phrase “fighting the borrow checker” to be shorthand for “I can’t write C or C++ in Rust and I want to”. They’re not the same language and the constructs are different



  • JavaScript alone is not a simple beast. It needs to be optimized to deal with modern JavaScript web apps so it needs JIT, it also needs sandboxing, and all of the standard web APIs it has to implement. All of this also needs to be robust. Browsers ingest the majority of what people see on the Internet and they have to handle every single edge case gracefully. Robust software is actually incredibly difficult and good error handling often adds a lot more code complexity. Security in a browser is also not easy, you’re parsing a bunch of different untrusted HTML, CSS, and JavaScript. You’re also executing untrusted code.

    Then there is the monster that is CSS and layout. I can’t imagine being the people that have to write code dealing with that it’d drive me crazy.

    Then there are all of the image formats, HTML5 canvases, videos, PDFs, etc. These all have to be parsed safely and displayed correctly as well.

    There is also the entire HTTP spec that I didn’t even think to bring up. Yikes is that a monster too, you have to support all versions. Then there is all of that networking state and TLS + PKI.

    There is likely so much that I’m still leaving out, like how all of this will also be cross platform and sometimes even cross architecture.