Live data from Hacker News

Deconstructing K&R C Is Dead (2015)

c.learncodethehardway.org

181–190 of 190 posts

Re: Deconstructing K&R C Is Dead (2015)

#181

Earlier quoted context omitted.

What in particular makes Rust (or Go or Swift) unsuitable?

Go is unsuitable as a replacement for C because it is garbage collected. End of discussion. Rust is unsuitable as a replacement for C because its memory management is poorly thought out (ie. its a joke). Here's the relevant paragraphs from the Rust FAQ. Really? "Rust avoids the need for GC through its system of ownership and borrowing, but that same system helps with a host of other problems, including resource manag…

> For when single ownership does not suffice, Rust programs rely on the standard reference-counting smart pointer type, Rc, and its thread-safe counterpart, Arc, instead of GC.

This is a library thing, not a language thing.

If single ownership is enough for you, go ahead and use it. But if you need a different memory management strategy, that is available too.

Rust, the language, provides a single clear memory management strategy. It also provides the ability to design your own abstractions for different strategies, and implements some of these in the stdlib.

C/C++ have refcounting and GC libraries too. Does that make them a joke?

Re: Deconstructing K&R C Is Dead (2015)

#182
post #81

Earlier quoted context omitted.

IMHO it is OK if you are only going to call a few simple one, but for calling a few hundred complex ones (callbacks with variable argument list, etc..), it becomes a bit cumbersome. BTW I am not implying that is Rust's fault, actually I can't think a syntax that would make it less verbose, and I am a huge Rust fan.

Not really, there are tools that can take C header files and spit out bindings. Rust also supports vararg C functions even though Rust itself doesn't support varargs. Writing safe Rust wrappers around these unsafe C bindings can sometimes be tedious, but this isn't worse than using C directly (which is inherently unsafe).

I didn't say it is not supporting them. I said that is a bit cumbersome to have to write the shims for them.

I wasn't aware of the tools that do this automatically. Just found one and it looks promising.

Re: Deconstructing K&R C Is Dead (2015)

#183
post #124
post #117

Earlier quoted context omitted.

> There's a reason languages like Rust and Go rely heavily on static linking and stack allocation This is untrue: Rust certainly does not do any optimisations linking statically by default, nor is there a difference between putting an array on the stack or on the heap. While it is true that code can benefit from whole-program optimisation, it isn't the default in either language, just like it isn't the default in C.

Languages which bake in automatic bounds checking at every access rely on optimization to recover the performance hit. Without static linking, automatic GC, and other constructs that's very difficult. LTO notwithstanding, once you add those more sophisticated constructs, iterating the language becomes more difficult. You don't hit upon the best method for implementing various types the first time, or the second time,…

> C isn't standing still, either. Strategies like SafeStack (see http://dslab.epfl.ch/proj/cpi/) can provide substantially the same safety guarantees as Rust in terms of real-world attack vectors, without having to modify any existing C software, and without giving up performance.

That paper indicates that you do in fact give up performance, and the performance is comparable to existing SFI techniques. SafeStack itself is insufficient to prevent UAF problems with the heap. CPI prevents them, but with significant overhead. And you still don't get full memory safety.

Re: Deconstructing K&R C Is Dead (2015)

#184

Earlier quoted context omitted.

Steve - did you read the FAQ? They really don't know what direction to go. At least Swift stuck with ARC, being a necessity as they were tasked with merging Swift with the Objective-C runtime for interoperability. Rust's multiple methods of memory management makes it strange, at best, for programmers to decide how to build a program or an API. Are the owners of Rust planning on adding a GC? Really?

Steve wrote the FAQ and most of the docs

I would hesitate to say I write the FAQ these days; after Brian's efforts to revamp it, it was VERY MUCH a community effort.

Re: Deconstructing K&R C Is Dead (2015)

#185

Earlier quoted context omitted.

You don't describe why you think it's a joke.

Steve - did you read the FAQ? They really don't know what direction to go. At least Swift stuck with ARC, being a necessity as they were tasked with merging Swift with the Objective-C runtime for interoperability. Rust's multiple methods of memory management makes it strange, at best, for programmers to decide how to build a program or an API. Are the owners of Rust planning on adding a GC? Really?

> Are the owners of Rust planning on adding a GC? Really?

To address this specifically: Current plans for Rust are mostly along the lines of adding the bare necessities in the stdlib to allow GC implementations to be written.

There are mostly-niche use-cases for having a GC in Rust. I've written some of the motivation here[1] (note that that blog post is about a pure library GC independent of Rust, which is different from what is planned; but the motivations are similar).

One major use case is if you want to talk to a language which has a GC. Say you're writing a native extension to a Ruby or Node and want to deal with the GCd types within Rust code in a safe way without pausing the GC. Or if you're writing an interpreter for a GCd language. Or you're writing some code that deals with complicated cyclic graph-like datastructures.

These are all pretty niche, but the workarounds in these cases aren't pretty so it's nice to have some form of GC capabilities in Rust. This is not a price you pay by default, and it's not something that affects anyone but the people who need these types. It will probably take the form of some low level APIs that use LLVM stack rooting to collect roots, and some traits in the stdlib, which can be used by an independent GC library (not part of the stdlib) or a language bindings library (also not part of the stdlib).

Rust itself will never get a GC as part of the language.

[1]: http://manishearth.github.io/blog/2015/09/01/designing-a-gc-...

Re: Deconstructing K&R C Is Dead (2015)

#186
post #156

Earlier quoted context omitted.

GC languages are almost certainly not even in consideration for most embedded applications. There aren't good strategies for general garbage collection that don't insert random pauses for starters, and you also have a non-negligible impact on RAM usage on systems where RAM might be a premium. A lot of the things rust brings to the table aren't always relevant on embedded platforms. Dynamic memory allocation on embedd…

> GC languages Rust is not a GC'd language, it essentially uses RAII to deterministically determine at compilation time when memory will be freed. > Dynamic memory allocation on embedded is the exception Rust fully supports running entirely without dynamic allocation. There is a subset of the standard library defined explicitly for this purpose.

> Rust is not a GC'd language

Right, I was referring to Go and Swift with the comment about GC. Since rust didn't have that problem, I mentioned why major adoption might not be forthcoming.

I understand that you can statically allocate all you want in Rust, but it's memory safety, particularly with regards to object ownership is one of its major selling points. Object ownership and lifetimes are trivial when everything is static.

The other arguable selling point to rust is its standard library, but much like C++ the standard library would be left aside in most embedded applications.

So it doesn't buy you much of anything at all, but it takes some work to setup, plus you are fighting the momentum that C/C++ has. Unless there is some other compelling reason to use it, I don't expect much adoption.

Re: Deconstructing K&R C Is Dead (2015)

#187

Earlier quoted context omitted.

GC languages are almost certainly not even in consideration for most embedded applications. There aren't good strategies for general garbage collection that don't insert random pauses for starters, and you also have a non-negligible impact on RAM usage on systems where RAM might be a premium. A lot of the things rust brings to the table aren't always relevant on embedded platforms. Dynamic memory allocation on embedd…

> A lot of the things rust brings to the table aren't always relevant on embedded platforms. Dynamic memory allocation on embedded is the exception, not the rule. Everything is statically allocated, so memory management is relatively simple -- everything sticks around forever. In that case, you can simply not use the dynamic allocation features of Rust, just as you can simply not use malloc() in C.

Absolutely, but then what does it buy you over C/C++? It has a few 'nice to haves' over that, but in this domain those won't tend to be nice enough to motivate most people to bother setting up toolchains purposed for it.

Re: Deconstructing K&R C Is Dead (2015)

#188
post #176

Earlier quoted context omitted.

> Try using Go or Rust (love both, x2 for Go) to allocate say a hundred GB of memory for some huge/fast in-memory data processing. Let me know how far you get. There is no fundamental reason why this should be slower or harder in Rust. Rust generally compiles down to more or less the same code C does. There are reasons why this could be slower in Go, but it really depends on what program you're writing, so it might e…

We have a few Go processes with high memory usage. For one in particular, while it's been higher in the past (~150GB), we're sitting at 40-80GB per node right now. The busiest node traffic-wise had average GC time over the past 20min of 3.4ms every 54.5s. 95th percentile on GC time is 6.82ms. That node is sitting at 36GB in-use right now, and has allocated (and freed) an additional 661GB over the past 20min. Can't re…

That sounds much better than the Java stories I've heard, which makes sense since Go is better at avoiding the heap.

No idea how it compares with others; and not sure if it is representative, but to me that sounds pretty decent.

Re: Deconstructing K&R C Is Dead (2015)

#189
post #182

Earlier quoted context omitted.

Not really, there are tools that can take C header files and spit out bindings. Rust also supports vararg C functions even though Rust itself doesn't support varargs. Writing safe Rust wrappers around these unsafe C bindings can sometimes be tedious, but this isn't worse than using C directly (which is inherently unsafe).

I didn't say it is not supporting them. I said that is a bit cumbersome to have to write the shims for them. I wasn't aware of the tools that do this automatically. Just found one and it looks promising.

Yeah, my point was that thin shims are free, and "thick" safe shims take effort but as far as comparing with pure C is concerned you only need to compare the cost of thin shims. C doesn't have safety so the concept of a thick, safe shim is nonexistant.

Re: Deconstructing K&R C Is Dead (2015)

#190

Earlier quoted context omitted.

The `tmp != head` comparion is UB because `head` is a dangling pointer after the first loop iteration, right?

Yep! To do this properly requires something more like: void free_circularly_linked_list(struct node *head) { struct node *tmp = head->next; while (1) { if (tmp == head) { /* Has to be a separate case since even assigning * a dangling pointer is UB I believe? */ free(tmp); break; } else { struct node *next = tmp->next; free(tmp); tmp = next; } } }

I'm not sure what you are trying to achieve by using the infinite loop. There's a more direct way.

    void free_circularly_linked_list(struct node *head)
    {
      struct node *a = head->next;
      while (a != head) {
        struct node *b = a->next;
        free(a);
        a = b;
      }
      free(head);
    }
Great example, by the way!
Post reply on HN