Earlier quoted context omitted.
Then learn an assembly language instead, because C also has a fair amount of bookkeeping hidden behind the scene. C is typically described as a "low-level" programming language, where the "low-level" normally refers to the supposed distance from the language to the actual hardware. But as many incidents with UB demonstrate, this distance is still quite larger than expected. I think there is another sense of the word…
> Then learn an assembly language instead Learn assembly TOO, not instead. I did, as part of computer architecture course. Very valuable. I think you should learn everything from transistor level up if you want to do serious programming. I don't think you need to actually use it, but it's sometimes very handy to know those things.
How can C Programs be so Reliable? (2008)
81–90 of 97 posts
Re: How can C Programs be so Reliable? (2008)
#82Earlier quoted context omitted.
So it is worse, therefore it is better? Exceptions are exceptionally good at error handling - they always do the correct default (bubbling up if not handled, bringing a stacktrace with them, and by default they auto-unwrap the correct return value, not making the actual business logic hard to decipher), plus they make error handling possible on as wide scope as needed (try block vs a single return value). I absolutel…
> Converse curiously; don't cross-examine. Edit out swipes. > Please respond to the strongest plausible interpretation of what someone says, not a weaker one that's easier to criticize. > Eschew flamebait. Avoid generic tangents. In particular you seem to be responding to a strawman, since nowhere did I say C error handling was better than structured exceptions. The parent asked what was functionally different betwee…
> in C the program is more liable to simply crash
I simply disagree with this statement, as silent failure is also very common in case of C, which is probably the worst option. (Especially that it may cause memory safety issues, that may not even materialize until much later).
No need to take my comment that seriously though, I had no bad intention whatsoever.
Re: How can C Programs be so Reliable? (2008)
#83I think the reliability gap is in statically typed, compiled languages versus dynamically typed languages. I think C++ is a good combination of both worlds. You don't have to type quite as much for error checking an manual management and you get a correctly typed program by default.
Static typing is useless without strict typing. Knowing the type of everything won’t save you if you can multiply a pointer by an integer and use the result as a file handle.
What language are you talking about? Go to godbolt and try that with any of the compilers there for C or C++.
Re: How can C Programs be so Reliable? (2008)
#84Earlier quoted context omitted.
> As the article says, checked exceptions are not the solution here. Java had a very bad model of checked exceptions (the OP was written in 2008). A correct way is to make it a part of the type system, though it doesn't have to be a sum type like Rust, and make any error-related code path as convenient as possible to use. > In C, you are forced to perform the NULL-check, or crash. You don't necessarily crash if you f…
> You don't necessarily crash if you failed to perform a NULL check! In the case of using the result from `fopen`, I don't know of a platform where a dereferencing of NULL (which happens in a separate translation unit, which is already compiled and linked, and will not be subject to LTO and other optimisations) within the various read/write/seek/tell functions doesn't result in an immediate crash. I fully admit that…
Although in a very different content, I have seen "dereferencing" a null pointer in C++ not crash immediately, if you dereference it to call a nonvirtual class member function, e.g,
t->foo();
Depending on how this gets compiled and the implementation of `foo()`, the segfault may not come at the line above, where technically `t` is being dereferenced. It may come inside `foo`, or somewhere further down the call chain. The resulting crash may not even manifest as a segfault.Re: How can C Programs be so Reliable? (2008)
#85Earlier quoted context omitted.
> Writing code with the occasional try/catch block isn't too different from writing C and not checking error conditions I think a critical difference is that in C the program is more liable to simply crash if errors aren't correctly handled, whereas in Java/Python/etc the program can just log a stack trace and keep on truckin', even if the bug is actually quite severe. In some cases a crash is preferable - e.g. if so…
So it is worse, therefore it is better? Exceptions are exceptionally good at error handling - they always do the correct default (bubbling up if not handled, bringing a stacktrace with them, and by default they auto-unwrap the correct return value, not making the actual business logic hard to decipher), plus they make error handling possible on as wide scope as needed (try block vs a single return value). I absolutel…
While writing code it's trivial to ask yourself if the next statement will include a call to a function which is not defined within a compilation unit under your control.
If it will, then you lookup documentation for that function to determine what it expects and how it can fail. Most of my functions which interact with such functions look like long sequences of this:
/* close the file */
ret = -1;
do {
errno = 0;
ret = close(fildes);
} while (0 != ret && EINTR == errno);
if (0 != ret) {
perror("Error");
goto off_ramp;
}
I've caused plenty of bugs in my career, but I can say with confidence that 0 of them had to do with ignoring/skipping proper error handling. You have to do so intentionally.Re: How can C Programs be so Reliable? (2008)
#86Earlier quoted context omitted.
> C is horrible for exploratory programming Completely disagree. The lack of screwing around selecting abstractions forces you to make something productive right away and not stress about refactor.
Who is stressing you to refactor when doing exploratory programming? Yourself? OOP languages? Society?
Re: How can C Programs be so Reliable? (2008)
#87I think every graduating student should work on a non-trivial application in plain C for a year before moving on to another language. It makes you exceptionally paranoid about failure states and practically requires a bit of thought and planning before attempting any non-trivial change. The mindset of "it's fine to ignore all error conditions and let the default exception handler print a stack trace to the user" resu…
Rust is better for this since your program won’t even compile until you’ve handled those error states.
If you run this
use std::fs::File; pub fn main() { let fp = File::open("test").unwrap(); }
You get this:
thread 'main' panicked at /app/example.rs:11:33: called `Result::unwrap()` on an `Err` value: Os { code: 2, kind: NotFound, message: "No such file or directory" } note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
The language incentives you to propagate errors up to main and then just let it fail.
Re: How can C Programs be so Reliable? (2008)
#88Earlier quoted context omitted.
Well, there are such tools for C, but wouldn't using them be detrimental in this context? Think, like using a debugger vs. trying to wrap the execution in one's mind: I'not saying that one shouldn't use debuggers, but not using one has benefits, as a teaching device. Like running in a weight vest. Edit: ah, perhaps you meant, in addition to using raw C, one should also learn how to use such static analyzers & cie
As the author notes, to know what C code does you need to run it. A good debgger is a C programmers best friend.
It can tell you that i = i++ increased i by 2, for instance. That might not even be true of another instance of i = i++ in the same object file being debugged.
There is no substitute for knowing what the C will do before it is run.
Re: How can C Programs be so Reliable? (2008)
#89Earlier quoted context omitted.
Rust is better for this since your program won’t even compile until you’ve handled those error states.
It will compile just fine if you call unwrap on a Result and then you get a wonderful error. If you call unwrap on a File::open() you do not even get the file name. If you run this use std::fs::File; pub fn main() { let fp = File::open("test").unwrap(); } You get this: thread 'main' panicked at /app/example.rs:11:33: called `Result::unwrap()` on an `Err` value: Os { code: 2, kind: NotFound, message: "No such file or…
Re: How can C Programs be so Reliable? (2008)
#90Earlier quoted context omitted.
Rust is better for this since your program won’t even compile until you’ve handled those error states.
Back when every developer had to build their own failure detection code and display messages to help themselves debug anything that meant that almost every developer was good at communicating errors to the user. Today developers don't build that skill, so you see applications that just fails silently everywhere or produce nonsense errors. The better developer tools you have the less your developers will need to learn…
Now its an exact line number with a little description of what went wrong and sometimes a suggestion on how to fix it.