8 ms·
Why do people act surprised that C and C++ are still as viable as ever, and still very widely used? Do they not know that basically every important piece of so
by PommeDeTerre 14y ago
Why do people act surprised that C and C++ are still as viable as ever, and still very widely used?
Do they not know that basically every important piece of software today is still written in those languages?
Has this realization somehow been lost over time with the rise of languages like Java, PHP, JavaScript and Ruby, even though the major implementations of those languages are themselves built using C and/or C++?
- berntb 14y agoI remember how shocked I was ten years ago when talking to a newly educated guy about languages -- and he didn't know any C?! Then I realized... "of course, they only learn Java now". I left for scripting a long time ago, but still: Sad.
- gnuvince 14y agoI think a lot of people are surprised that C and C++ are still widely misused. Certainly for a lot of domains, their performance characteristics are not only attractive, but essential to the success of the application. But in many other domains, they could be replaced with other languages that would offer performances that are just as good, and be safer. For example, I go on IRC with weechat, which is written in C. An IRC client spends most of its time idling, waiting for network data or input from the user, so certainly it could be written in a language like OCaml.
- alexchamberlain 14y agoModern C++ is just as safe as any language. Unfortunately, you need to find a good tutorial that doesn't go low level before you need it.
- tptacek 14y agoThis is simply not true.
- PommeDeTerre 14y agoCare to elaborate? Keep in mind that the "modern C++" mentioned involves the use of things like RAII, smart pointers, the STL and Boost, rvalue references, move constructors, and the buffer overflow production offered by the major C++ compilers. The use of pointers and direct pointer manipulation, for instance, can often be completely avoided with ease these days. That cuts out a large number of potential problems. It's a much different situation than it was in the past.
- huhtenberg 14y agoSafety implies clarity. Smart pointers, Boost, rvalue references and move constructors is exactly the things that obscure the hell out of the code, frequently making it incomprehensible to anyone but the author. Crashing on a dereferenced NULL pointer is peanuts compared to clusterf#ck of logic that stems from a mess in the dev's head. C++ is less safe because its adepts, on average, are sloppier and messier than those who favor other languages (C included).
- to3m 14y agoYou're right that people tend to overestimate the difficulty of debugging crashes and memory leaks. A lot of C++ code I've seen has tried to move heaven and earth to ensure that mistakes are impossible, at the cost of introducing a lot of rather expensive (time to write, time to execute, time to maintain) infrastructure - or baggage, if you're unkind - that also make things unclear in the debugger. This isn't quite a waste of time, but it's been my own experience that it's cheaper to just make things as straightforward as you can, then simply ask everybody to try not to make mistakes. Often you can build in systems that make it easy to diagnose problems when they occur, or just rely on people's debugging skills. Some programmers consider this a total cop-out - they're right, I should be ashamed - but I've found the overall TCO to be lower. You might have to find this out the hard way to believe it. The worst thing is that some people think the alternative should be C ;)
- betterunix 14y ago"The use of pointers and direct pointer manipulation, for instance, can often be completely avoided with ease these days" Really? I am pretty sure there are a large number of STL implementations that give you a pointer when you ask for a vector iterator. I suppose you could avoid iterating on vectors, but you would also have to avoid operator[] (which by default performs no bounds checking, so the pointer arithmetic is just as unsafe as it would have been with a primitive array type); you'd be stuck with at(), which few compilers will optimize even if it could be shown that the index will never be out of bounds. "That cuts out a large number of potential problems" Yet the language encourages programmers to do things the unsafe way. It is a lot less effort to use a low-level pointer type, a fixed-width integer type, etc. than to use smart pointers, STL containers, iterators, Boost (which is not even standard), and so forth. Just as an example, a C++ programmer must first choose between multiple smart pointer types (where should you break your pointer cycle with a weak_ptr?), whereas a primitive pointer is easily accessible and requires no decision-making (this was the pattern with casting: C-style casts are much more convenient than static_cast, dynamic_cast, or const_cast, and so you saw C-style casts being used all over the place). While a Java or Python programmer on a tight deadline might produce slow code, a C++ programmer will produce unsafe code that is far more likely to have bugs (even if the high-level design is bug-free).
- Espressosaurus 14y agoshared_ptr helps, but it won't cure your circular dependency blues. When do you allocate on the stack vs. on the heap? It matters, and is something you don't have to think about in Python or Java or C#. Are you passing by value or by reference? Are you passing a pointer by value? What's the actual behavior when you use the unary * operator? The copy constructor? The assignment operator? When you use MyType foo = 3;, what's actually happening? Did you mean to use the implicit constructor, or was that a programming error? And then you have all the warts related to the single-pass compilation and inlining of headers because that's the way C++ does things...and let's not get into the misfeatures that were brought over due to C compatibility, like macros. So no, C++ is not as safe as any language. It is manifestly unsafe. It can be a bit easier to manage its complexity with C++11, but it's still far from safe. And C++11 makes the language even larger and more complex...
- PommeDeTerre 14y agoI'm not sure what you're getting at. Circular references are a problem in other languages, too. The existence of Java's java.lang.ref.WeakReference, or .NET's System.WeakReference, or Python's weakref illustrate this. When it comes to heap or stack allocation, you may not even have a choice, depending on the language being used. At least C++ gives you the option of choosing in many cases. And C# does allow for both heap and stack allocation, by the way. Likewise for the other issues you mentioned. Sure, they may have been a problem for some developers in the early 1990s. Things have changed. The language has evolved to offer ways of dealing with such scenarios, often in a much safer fashion. We now have rvalue references, move constructors, the explicit keyword, and other functionality at our disposal now. It's not at all difficult these days to write high-level C++ code that's safe and robust. The best part is that it offers all this, without taking away the power to go deeper or to do more complex or riskier things, if the need arises. But in no way are you forced to do things unsafely these days.
- jrockway 14y agoWeak references are more for keeping things like hash keys from creating a reference than for preventing your program from segfaulting. Object lifecycle and reference counting are two completely different things that only appear to be related. Even if you figure out your C++ auto_smart_magic pointers, you still have to decide when the object you're referring to is no longer necessary, just like you would in Python or Java.
- betterunix 14y agoConsidering how difficult it is to handle errors in C++, I am not sure you can say it is just as safe as "any" language. Exceptions can be used, except that they cannot propagate out of destructors, they should not propagate out of constructors, and there is no standardized way to retry the operation that threw the exception. "you need to find a good tutorial that doesn't go low level before you need it." In other words, don't program in C++ at all. The default numeric type in C++ is fixed-width (int or floating point), the default string type is a primitive pointer (const char *), and you still see low-level pointer types tossed around as iterators (e.g. for the standard vector class).
- alexchamberlain 14y agoThe iterator for a vector is a class... although quite a thin wrapper around a pointer, it is still a class. The difficulty to handle errors in C++ is generally bad API design left over from the C days. Exceptions used correctly make error handling exceptionally easy.
- AnthonyMouse 14y agoYour criticisms would be well taken if they were actually true: >Exceptions can be used, except that they cannot propagate out of destructors Exceptions are perfectly well allowed to propagate out of destructors. A destructor throwing an exception is only considered ill advised, because destructors are called during stack unwinding when another exception is propagating, and throwing an exception during another exception causes program termination. And object destruction is largely incapable of truly failing anyway: There will be no state remaining to be left inconsistent because the object is going away, unless the destructor is interacting with an object not being destroyed, in which case the error is actually with the other object and information about the error can be stored with that object or in an error queue and handled in due course after the stack unwinding is complete. Moreover, what's your solution to the problem? If the destructor is doing nothing but deallocating memory (and calling other destructors that only deallocate memory) then it never needs to throw and there is no problem. If it's doing something else then it's either doing something that another language wouldn't allow because it has no destructors (in which case you can refrain from doing it in C++ as easily as you can switch to one of those languages), or the other language has an equivalent to destructors and then will have the same issue with throwing during exception propagation. Do you see some solution to having it both ways? >they should not propagate out of constructors Rubbish. Constructors don't even have return values. Throwing exceptions is the canonical way of indicating construction failure. The primary benefit to non-throwing constructors is that it allows certain performance optimizations. For example, if a constructor throws during a std::vector resize operation, the vector class will undo everything that had been done during the resize operation so as to leave the vector in a consistent state. This is easy with copy constructors: Just destroy the copies and keep the originals. But if vector used the move constructor to move the existing elements to the newly allocated internal array then the originals are no longer valid. So vector's resize will only use the move constructor instead of the copy constructor if the move constructor is declared noexcept (or the compiler can statically determine that it doesn't throw), since the alternative would violate the vector's ability to maintain consist state when a move constructor throws an exception. >there is no standardized way to retry the operation that threw the exception. How about catching the exception, addressing it, and retrying the operation in the try block? What do other languages do that you feel is superior? > The default numeric type in C++ is fixed-width (int or floating point) Why do you believe this to be a serious limitation? The range of a 64-bit type is more than sufficient for the overwhelming majority of applications and for the few remaining with specialized needs (you know who you are, cryptographers and mathematicians), arbitrary precision libraries are readily available. > the default string type is a primitive pointer (const char *) The default string type is std::string. Which can even be used with the large bulk of the C library through the helper function string::c_str() which provides a "safe" temporary const char array for passing to C library functions.
- pcwalton 14y agoNo, this is not true. Until C++ can reason carefully about aliasing, it can't be memory-safe. Iterator invalidation and reference invalidation are the key problems here. Rather than repeat the code examples in detail, I'll link to some earlier examples I've shown: http://news.ycombinator.com/item?id=4724781 http://news.ycombinator.com/item?id=4724781 http://news.ycombinator.com/item?id=4724421 http://news.ycombinator.com/item?id=4724421 Basically, they come down to references and iterators not knowing about aliasing, thus being unable to determine when the referent is destroyed.
- joe_the_user 14y agoModern c++ can be as safe as any language given rigorous guidelines and methods. But X project put together with "programmers off the street" is likely to involve some portion of crashes through sloppy coding. The thing is that you have to clarify safety and danger. In more application than people would like to acknowledge, slowing down to the point of unusability can be as much of a dangerous result as crashing with a null pointer. Slowness has been standard quality of Python and Ruby development as much as null pointers have been a standard quality of c/c++ development. Either can be avoided with proper care but these all somewhat different failure modes. The one thing is that c++ do present a different kind of security risk than Ruby/Python slow-downs or even Ruby/Python crashes. Despite this, a some point you still have to consider the tradeoffs.
- jlgreco 14y agoIRC clients are a bad example considering that they are often used on hosts that you can't count on having much more than a C compiler. Super-lightweight VPSs, free accounts on school servers, etc. Nobody wants to boostrap another language in their $HOME just to use IRC.
- calpaterson 14y ago> Do they not know that basically every important piece of software today is still written in those languages? A blatant overstatement. There's lots of important work done for the CLR (MS, many others), Java (Sun, Google, Amazon, bits of Facebook, IBM, etc, etc) or in Python (Dropbox) or in Cobol (banks...sigh). Yeah, there's plenty of important C/Cpp code but it's probably in a minority of "important", even if important just means "commercial" or "popular".
- alayne 14y agoI disagree. Most operating systems, desktop applications, web browsers, and fundamental Internet services (web servers, BIND, MTAs, etc) are written in C/C++. Dropbox is not in that league of important.
- rayiner 14y agoMost of those applications were written decades ago.
- calpaterson 14y agoSo you're arguing with me over what "important" means. If "important" means nearer the bottom of the stack, then yeah, you win. I doubt many people see it that way though.
- paul-woolcock 14y agoIf by "bottom of the stack" you mean "the code that the top of the stack depends on in order to run at all," then I would say that he is correct in what "important" means.
- kbutler 14y agoInfrastructure only exists to enable applications, though it's easy to lose sight of this as a software engineer.
- adamnemecek 14y ago
- doktrin 14y ago>> Has this realization somehow been lost over time with the rise of languages like Java, PHP, JavaScript and Ruby, even though the major implementations of those languages are themselves built using C and/or C++? This feels like an oversimplification. There are surely very good reasons to choose [insert language other than C] for production / prototyping / development purposes. The fact that [language] was built in and / or relies on C libraries is at that point not central to the discussion.
- betterunix 14y ago"Why do people act surprised that C and C++ are still as viable as ever, and still very widely used?" Surprised? No, I'm terrified. It is scary to think that critical systems are written in poorly defined languages that encourage programmers to create buggy, unreliable software. "Do they not know that basically every important piece of software today is still written in those languages?" That is a problem that needs to be (slowly) corrected. We can start by not writing tomorrow's important software in those languages.
- jawr 14y agoBut C/C++ are the building blocks for all these other languages, your argument seems to suggest that it's impossible to write critical systems in these languages.. but what would the alternative be? Surely if this is the case we can't use Linux as it's written in C, or we can't use Java because it's C++ based... A poor workman blames his tools.
- betterunix 14y ago"C/C++ are the building blocks for all these other languages" Not necessarily. The SPARK compiler was originally written in Ada. Python is moving towards a bootstrapped model with PyPy. Lisp compilers have been written in Lisp. There was a Perl 6 interpreter written in Haskell. The HaXe compiler is written in OCaml: https://en.wikipedia.org/wiki/HaXe#Compiler_implementation_and_performance https://en.wikipedia.org/wiki/HaXe#Compiler_implementation_a... "your argument seems to suggest that it's impossible to write critical systems in these languages" Obviously it is not impossible, given how many such systems are out there. It is just scary. "what would the alternative be?" Well, these guys may be on to something: https://en.wikipedia.org/wiki/Altran_Praxis https://en.wikipedia.org/wiki/Altran_Praxis "Surely if this is the case we can't use Linux as it's written in C" Would you trust your life to the Linux kernel? Would you be comfortable with that? I still see the occasional kernel panic; how would you like a kernel panic that sent your car swerving into a tree? "we can't use Java because it's C++ based..." ...or we bootstrap our compilers and programming systems, and let C++ fade away (as it should). What stops us now is the volume of code, but we could go a long way by just not writing more C++ code, so that the problem does not continue to expand.