11 ms·
Some Were Meant for C – The Endurance of an Unmanageable Language (2017) [pdf]
- slicktux 4y agoUnmanageable really has a context and depending on the use case sometimes C is the best option…
- adrianN 4y agoThe use cases where C is the best option are probably limited to exotic platforms that don't have compilers for better languages. There aren't many targets were you can't at least use C++.
- torstenvl 4y agoYour comment seems to assume C++ is a better, safer language than C. I know a number of people who would sharply question that assumption. I for one really hate destructors. They mean you can never tell what `delete` does. I remember a nasty double-free bug I had because of that.
- PaulDavisThe1st 4y agoCongrats on providing yet another reason why software should be at least open source (if not actually libre)
- moshegramovsky 4y agoWell I guess it's a good thing no one ever had a double free in C :) > They mean you can never tell what `delete` does. Can you elaborate on this? A destructor is a function that's built into an object. It's really not more complicated than that. If malloc/free are functions that should be used in pairs, then the constructor/destructor pair tries to provide a convenient and structured way to know where malloc/free go. You would call new in the constructor and delete in the destructor. I'm curious to know what you prefer?
- stevenhuang 4y agoCases can arise where ownership of objects are not clear (which is a separate issue) but when they do occur, you can have a custom destructor that frees a lot of other objects, and then these other objects may in fact be "owned" elsewhere. Somewhere down the line these other objects are freed again, causing double free.
- adrianN 4y agoHow would malloc/free be better in that situation?
- ihatepython 4y agoI don't know, but when I use C, I like to statically allocate everything if at all possible, I don't free() anything, I let the OS clean everything up at exit(). A lot of the small Unix utilities don't necessarily need dynamic memory allocation IMO
- adrianN 4y agoThat's a good strategy in C++ too. Check the MISRA guidelines for example.
- stevenhuang 4y agoI'm not saying it's better, it wouldn't. Parent was asking in what scenarios can custom destructor causes issue so I just provided one.
- torstenvl 4y agomalloc/free are better because free(window) could never call free(window->widget->font)
- scaredginger 4y agoThis sounds much more like a case of awful design than destructors being problematic
- spacechild1 4y agoFirst off, new/delete are only used for objects that are allocated on the heap. Even then, modern C++ has RAII wrappers such as std::unique-ptr. You should only need new/delete in rare cases.
- nlehuen 4y agoThis. Over the last few years of writing C++ on a daily basis, I can count the number of times I used `delete` on both hands (maybe one hand actually). `new` was harder to get rid of because of some flaw in the framework we used, but that has been fixed now. Unless you are in the business of writing smart pointers yourself, you should never have to use those keywords anymore.
- deleted 4y ago[deleted]
- torstenvl 4y agoBy default, unique_ptr calls delete. It therefore still calls the destructor. So this has literally no bearing on the problem. It doesn't help at all.
- spacechild1 4y agoOf course it calls the destructor. What else should it do? The point is that you don't get any double frees, because you never have to call delete manually. Or maybe I misunderstood your complaint?
- AlotOfReading 4y agoC still fills a niche nothing else really does in terms of being a lingua franca everyone can read that any language can talk to. The language is stable enough that code written today will probably have the same semantics far into the future, something C++ has been a lot more shaky about historically.
- Joel_Mckay 4y agoI lol every-time someone quotes their favorite JIT language that is essentially a meta-circular compiler for C library bindings. “It can scarcely be denied that the supreme goal of all theory is to make the irreducible basic elements as simple and as few as possible without having to surrender the adequate representation of a single datum of experience.” ( Albert Einstein )
- pjmlp 4y agoUnfortunately we cannot get rid of the underlying OS ABI unless targeting bare metal.
- pjmlp 4y agoOnly when there isn't a C++ compiler around, even if we restrict ourselves to the common subset, C++ has stronger type safety, while constexpr + templates are way better than macros.
- tmtvl 4y agoYeah, but if C++ is an option you can just as well skip over all the way to Rust, which is a better C++.
- pjmlp 4y agoExcept the small detail of missing tooling and ecosystem. There are lots of scenarios where C++ is the only available alternative to C, with similar tooling level and libraries.
- rootw0rm 4y agoI love C. It's what I learned after learning MASM style Intel assembly. I have a project still at the planning stage. I have many Rust crates lined up. So far I really like the bits of Rust I have learned. C plus generics? Sign me up! But damn, after coming from really awesome IDEs like Visual Studio, it just seems like it's taking me forever to make progress. Right now I'm asking myself, does Rust save me time in the long run from chasing down bugs? I'm not really sure, because I think I'm already decent at avoiding C foot guns.
- Joel_Mckay 4y agoThe use-case for Rust is not the same as C. In general, C is a better option if you find you are escaping to macro defined Assembly or other memory ops (glib back-ported data structures for C highly recommended). Rust likes to keep unsafe operations organized, but is a persistent pain if a problem scope requires many "unsafe" operations. I'd wager Rust will end up like Boost... really cool.. but too chaotic to trust past 10 months. =)
- froh 4y agoI don't get the 10 months part. is it some reference?
- Joel_Mckay 4y agoIt refers to the degenerative nature of iterative specifications: https://en.wikipedia.org/wiki/Second-system_effect https://en.wikipedia.org/wiki/Second-system_effect i.e. the attempt to "improve" ultimately adds additional complexity, and defeats its stated purpose due to conflicting use-cases.
- mlindner 4y agoI'm not sure if I agree with any statement of the form "The use-case for Rust is not the same as foo." for any foo where Rust is replacing a language that replaced foo. Rust is replacing C++ in several well documented places, however C++ itself was a replacement for C in many places. So by definition the use-case for Rust overlaps the use-case for C. Arguments like this sound like old arguments that were re-told to me by my father where people argued that C couldn't replace the use case for Algol at the University of Michigan MTS system. (Assuming I'm remembering the second-hand argument right. I'm a second generation software engineer.) Also, there's nothing of note in the last 10 months about Rust that's different from the 10 months before that.
- DieBruderBauer 4y agoI hated learning/using C. Once I was introduced to C++, it was like a breath of fresh air. Sure, at lot of it stylistic in nature. But those frameworks matter. They really do.
- pjmlp 4y agoThat was my path, back in 1991-92, coming from Turbo Pascal, C felt like a step backwards, luckily the teacher that provided us with Turbo C 2.0 for MS-DOS, also had a copy of Turbo C++ 1.0 around, and thus I became the only kid in class that would rather use C++ when given the option.
- graphviz 4y agoYesteryear?
- deleted 4y ago[deleted]
- mlindner 4y agoThis entire article seems to amount to "I am used to C, thus I don't see the problem with C." which is a fine position to have, but it's a perspective unique to the writer and others like him. It doesn't apply to people learning new languages that aren't C. Also several statements about how C must be used because somehow it's closer to the real world/hardware than other languages. Which is easily shown to be false given that hardware designers have had bend backwards and into contorted shapes to emulate the hardware environment that C was originally created to work against. This great article is a nice rebuttal of that: C Is Not a Low-level Language: Your computer is not a fast PDP-11. https://queue.acm.org/detail.cfm?id=3212479 https://queue.acm.org/detail.cfm?id=3212479 These types of arguments feel like they come from people who don't realize how much the compiler reworks your code to make it act like it does what you told it to do.
- keithalewis 4y ago[flagged]
- pprotas 4y agoIt was not worth reading but it was worth clicking the reply button? Not sure what you mean by “rant”, he makes some good points.
- snickerbockers 4y agoNo, the problem is not that modern CPUs want to be a PDP-11, it's that they want to be an 8086 for compatibility reasons. From the software's perspective, the ISA *is* the hardware. It doesn't matter if the CPU is internally recompiling everything to a RISC-like architecture with an arbitrary number of registers because there's nothing i can do to access that. If there's ever a radical new ISA which supplants x86 where C's constructs prove to be a bottleneck, and that ottleneck only applies to C, you will finally see it fall to the wayside. >These types of arguments feel like they come from people who don't realize how much the compiler reworks your code to make it act like it does what you told it to do. I guess it's hard to argue against a vague undefined term like "rework" but i can assure you that the output of gcc largely resembles what i expect it to. If the compiler does something bizarre i will know about it because i actually do check the assembly.
- waiseristy 4y agoThe primary benefit to C is that it is simple. And that is IMO the reason why it has such sticking power. The entire language & toolchain is understandable at a fairly core level without too much effort. Please don’t start a C flame war either HN. I know I’m nerd sniping you all on this one
- cycomanic 4y agoI would argue it's very easy to think one understands it. However I would wager most people who say they understand C don't really know many of the undefined behaviour cases and their implications.
- waiseristy 4y agoI would bet that the vast majority of undefined behavior encountered is when interacting with the standard library though. Which isn’t really the languages fault (But, I also totally concede that a language is inseparable from its std lib in reality)
- deleted 4y ago[deleted]
- Espressosaurus 4y agoThe number of people I have interviewed that have used C and C++ for years and can't tell me what undefined behavior is is too damned high. I've had one or two, and only one of them could give me a coherent answer of what the compiler is allowed to do if it runs across it. In my experience it's only the language lawyers who actually know what to look out for, and there are damned few of them. Which is stupid since undefined and unspecified behaviors are hugely important to how C and C++ are used in the field.
- waiseristy 4y agoWe’ve been really spoiled by modern compilers and operating systems which let you get away with large swaths of undefined behavior. You typically don’t know what is hidden from you
- pjmlp 4y agoLike others were made for JavaScript and PHP. Had it not been for UNIX freebie, it would had been a footnote like so many others. Outside UNIX clones and the few surviving embedded workloads without alternative, there is hardly a reason to reach for it instead of C++, which is also a UNIX child.
- sacnoradhq 4y agoNull was a trillion dollar mistake. Pointers and pointer math were a 10 billion dollar mistake. Unchecked array access is a several billion dollar mistake. Goto has its place: consolidated resource error unwind cleanup. That's basically its only valid use except for mechanically-generated finite state machines. Beyond that, don't bother. Other programming languages use reference counting and lifetimes to manage resources. int foo() { void *b0 = malloc(1000); if (!b0) goto err0; /* do something */ void *b1 = malloc(1000); if (!b1) goto err1; /* do something else */ void *b2 = malloc(1000); if (!b2) goto err1; /* keep going */ /* ... */ free(b2); free(b1); free(b0); return 0; err3: free(b2); err2: free(b1); err1: free(b0); err0: return 1; }
- simplotek 4y ago> Null was a trillion dollar mistake. I don't agree. Null is just a tombstone value. If you're dealing with specifying memory addresses, you either specify the address or point a value that tells you the variable is not pointing to an address. If anything, conflating arrays with pointers was a bad idea. The language would be far better equiped to deal with memory safety issues if an array data type included info like total size, used size, and perhaps also stride length. Relying on tombstone values to delimit strings or arrays was just prone to blow up on everyone's face.
- eterevsky 4y ago[flagged]
- deleted 4y ago[deleted]
- shadowofneptune 4y agoThe article raises a good point about object files and binary compatibility being neglected in more recent languages.