Hacker News new | ask | show | jobs
by valuearb 3276 days ago
As someone who spent over 20 years writing applications in C, anything built on C is crap and that includes C++ and Objective C.

Writing code is fun and interesting. But most software development is not writing code. It's a little bit of build management, even more testing, but mostly it's debugging. Debugging is not as fun as writing code. Every language feature that makes debugging more necessary, harder to do and more time intensive sucks. Dangling pointers are the absolute worst.

I can easily give up multiple inheritance for a more functional language that's far easier to write correct code in.

4 comments

> As someone who spent over 20 years writing applications in C, anything built on C is crap and that includes C++ and Objective C.

Maybe that the problem, if you see C++ as something "built on C" then it logical that the see a lot of the same problem. C++ evolved from C to specifically address a lot of the weakness in C.

> Every language feature that makes debugging more necessary, harder to do and more time intensive sucks. Dangling pointers are the absolute worst.

language design is an exercise in compromise, and there is space for multiple compromise points on the spectrum. C++ decided (for better or for worst) to go for performance vs nice debugging experience.

> I can easily give up multiple inheritance for a more functional language that's far easier to write correct code in.

Am i the only getting tired of this kind of blanket statements ?

The problem with C++ is, that for all its added complexity and powers, most C code still is correct C++ code, especially all the unsafe pointer manipulations. And there is no real performance reason. Many static typed languages compile to code as fast as C - if not faster thanks to tighter semantics. (Other than that some C compilers are better quality because of the effort went into them due to language popularity rather than any language feature)
> most C code still is correct C++ code Syntaxicaly yes, but with a more precise semantic and clearer stated "undefined behavior". The canonical example is the work around type punning and such.

> And there is no real performance reason. Many static typed languages compile to code as fast as C - if not faster thanks to tighter semantics.

Speed is only one part of the equation. For stuff like drivers and low level embedded development, we still needs C like unsafe memory manipulation. Rust,D,C# etc all have ways to do that.

> Many static typed languages compile to code as fast as C - if not faster thanks to tighter semantics. (Other than that some C compilers are better quality because of the effort went into them due to language popularity rather than any language feature)

Let's just agree to disagree on that one

With Valgrind, I would say dangling pointers are a solved problem by now. The real debugging headaches in C++ come from stuff like autogenerated constructors, overloading, template specialization, and other features that change semantics without requiring the syntax of the code that experiences the change to reflect that change. My unpopular opinion is that exceptions also fall into this class of dark features.
> With Valgrind, I would say dangling pointers are a solved problem by now.

Given the frequency with which use-after-free vulnerabilities are discovered in C++ programs, I’d say they’re not a solved problem. Valgrind is great but it doesn’t help when the only inputs that cause bad behavior are bizarre attacker-generated ones.

Only on the platforms that support Valgrind, with teams that bother to use it.

Given that Apple, Microsoft and Google keep doing presentations about such tools at their conferences, and my experience at enterprise level, I would say not so many bother to use them.

Avoiding dangling pointers requires a bit of discipline in pre-ARC Objective-C and C++, but now that we have ARC, isn't ObjC pretty much as safe as Swift? (Unless you explicitly use "assign" properties, of course.)
Apparently, the elegance of ObjC's handling of nil objects is considered also "unsafe" these days. I disagree with that specifically.
Objective-C's solution had its downsides, though. The classic `[firstName stringByAppendingString:lastName];` being fine when `firstName` is nil, but not if `lastName` is (though it doesn't always crash if `lastName` is nil – it's fine if `firstName is also nil!). Or how `[myObject isEqualTo:myObject]` returns false if `myObject` is nil. Or how adding a nil object to an NSArray doesn't crash (but is likely a bug!) when calling `arrayWithObjects:`, but does crash when it's an array literal.

These aren't world-ending problems, and you learn the rules easily enough, but it's like Objective-C only solved 1/2 of the problem.

Then there's the really strange corner cases, like how sending a message to nil was undefined behavior:

- when expecting a returned struct, before Apple switched to LLVM 3.0 (would vary depending on the platform's ABI, as well as the size of the struct) - when expecting a returned floating-point value on PPC <= 10.4, - when expecting a returned `long long` on PPC (it happened to return `(long)selector`)

For the record, I always loved how Objective-C handles this – I definitely preferred it to Java, Ruby, etc. where you're constantly checking for null or catching NPEs. But I like Swift's solution even more. I no longer have to remember about which parameters are nullable, or sanitize my inputs with `NSParameterAssert`s, etc.

Edit: also, `NSNull`. Ugh.

No because there is the whole C part of Objective-C, including UB.

So unless there is some validation of 100% of the code writen by the team and third party libraries, it is impossible to ensure there aren't C style coding tricks being used.

Also ARC only applies to Cocoa like classes, there is no bounds checking, implicit casts are like in C, C style strings are still used in many APIs, and this are just a few examples of unsafety.

TFW you code in Object Pascal and don't have C-trubz