Live data from Hacker News

Contracts for C

gustedt.wordpress.com

41–50 of 114 posts

Re: Contracts for C

#41
post #26

Earlier quoted context omitted.

> The complexity of C# and C++ should be a warning, not something to strive towards. I think this talk about "complexity" is a red herring. C++ remains one of the most popular languages ever designed, and one of the key reasons is that since C++11 the standardization effort picked up steam and started including features that the developer community wanted and was eager to get. I still recall the time that randos crit…

I agree. A lot of new additions to C++ make coding with it simpler, not more complex. However it does mean there's more to learn, because the old style of the language still exists and is still accepted by the modern compilers as opposed to say, Rust which removes replaced language features when it releases a new edition.

Language, not libraries.

Editions are rather limited in what they support.

Try to design a crate that stays compatible across editions, while using libraries that have changed signatures across editions.

The crate itself keeps its own edition fixed.

Re: Contracts for C

#42

Earlier quoted context omitted.

The complexity of C# and C++ should be a warning, not something to strive towards. C++ has 3 reasonable implementations, C has hundreds, for all sorts of platforms, where you don't get anything else. Most C developers don't want a modern C, they want a reliable C. WG14 should be pushing for clarifications on UB, the memory and threading model, documenting where implementations differ, and what parts of the language c…

C++ historically had much more implementations. It is probably more about the availability of quality compilers that are free to use and adapt, because even in C most new compilers for niche platforms are now based on GCC or clang for the practical reason.

Both implementated in C++.

As someone that remembers the t-shirts with "my compiler compiles yours" that some C folks used to wear, it is kind of ironic having that turned around on them.

Re: Contracts for C

#43

Earlier quoted context omitted.

The complexity of C# and C++ should be a warning, not something to strive towards. C++ has 3 reasonable implementations, C has hundreds, for all sorts of platforms, where you don't get anything else. Most C developers don't want a modern C, they want a reliable C. WG14 should be pushing for clarifications on UB, the memory and threading model, documenting where implementations differ, and what parts of the language c…

> The complexity of C# and C++ should be a warning, not something to strive towards. I think this talk about "complexity" is a red herring. C++ remains one of the most popular languages ever designed, and one of the key reasons is that since C++11 the standardization effort picked up steam and started including features that the developer community wanted and was eager to get. I still recall the time that randos crit…

The vast majority of C programmers will agree that they don't care for any of the new features, as is clearly evident by the fact that almost nobody elects to use the latest standards.

The "most popular programming languages" are irrelevant here.

C and C++ are standardized languages, and also the tools we use for code that actually matters. A standard that can't be implemented is worthless, and even the "3 high quality" implementations of C/C++ haven't fully implemented the latest 2 editions of either language.

There's a lot more riding on these two languages than you give credit for, and they should be held to a higher standard. C is not the language to experiment with shiny new features, it's the language that works.

> I can tel you that as a matter of fact a key reason why the likes of Rust took off

So what's the problem? If Rust is gaining traction on C/C++, and people are excited about what it brings to the table, use it. We'll both do our thing, let it play out - we'll see which approach yields better software in 10 years.

Re: Contracts for C

#44
The author writes that contract_assume invokes undefined behaviour when the assertion fails:

    #define contract_assume(COND, ...) do { if (!(COND)) unreachable(); } while (false)
But this means that the compiler is allowed to e.g. reorder the condition check and never output the message. (Or invoke nasal demons, of course).

This doesn't make much sense. I get that you want the compiler to maybe do nothing different or panic after the assertion failed, but only really after triggering the assertion and the notion of after doesn't really exist with undefined behaviour. The whole program is simply invalid.

Re: Contracts for C

#45
post #2

I like Eiffel. But if I want to use Eiffel, I’ll use Eiffel (or Sather). I’d rather C remained C. Maybe that’s just me?

Ada / SPARK has contracts, too, that can be proven at compile-time. In fact, Ada alone suffices, it has pre- and post-conditions. I think Ada has more libraries than Eiffel does. Does anyone even write Eiffel? I am really curious if it is still alive anywhere, in some form.

Re: Contracts for C

#46

There's a bit of an impedence mismatch with Contracts in C because C++ contracts exist partially to rectify the fact that is broken in C++. Let's say you have a header lib.h: inline int foo(int i) { assert(i > 0); //... } In C, this function is unspecified behavior that will probably work if the compiler is remotely sane. In C++, including this in two C++ translation units that set the NDEBUG flag differently creates…

I think the main point of pre- and post-conditions is, that the compiler can see them and prove that they match and will never be triggered. There probably will be a compiler flag for outputting all non-proved pre/postconditions, there is already -fanalyzer.

I think these conditions should be part of the type signature, different to what was suggested in the otherwise good talk you cited.

Re: Contracts for C

#47
post #38

Earlier quoted context omitted.

That's an entirely different thing (VLAs)

There's no VLA in my example.

Your example doesn't do any bounds checks, it just lets you get the sizeof. And the reason the sizeof works is the VLA infrastructure (which is not supported by MSVC so it won't compile the code).

What I want is -fbounds-safety from clang.

Re: Contracts for C

#48

Earlier quoted context omitted.

In C, sure. C is a dangerous language of its time. But these contracts don't make things better. Now you're removing control from the user. So now if an allocation fails, you crash. No way to recover from it. No getting an error signal back (NULL) so that you can say "OK, I need to clear up some memory and then try again". (Note that I'm not saying that inline error signaling such as NULL is good design - it's not).…

I'm not convinced. If something is going to cause a crash, like a nullptr, I'd rather crash near where the error happened with a nice error message, than hitting some UB crash god knows where. Do I want my app to crash at all? No, of course not. If it's crashing, there's a serious bug. At least now I know where to look for it. Should we pass back up an error signal instead of crashing? Yes, if it all possible, do tha…

I think the point is about e.g. malloc as shown in the blog post. The stdlib function already have return values to indicate invalid arguments from the caller. These exist to allow the caller to decide what to do in this case. Replacing them by invoking UB or panicing, means the user looses control.

Having the stdlib expose both ways, means either having two stdlibs (like on MS Windows), or dynamic checks in the stdlib. I don't think either way is a good idea. Thus, these contracts can't be used by libc.

Re: Contracts for C

#49
post #25

Earlier quoted context omitted.

It was proposed by Walter and denied by Stroustroup, probably to save C++. Karma hits back and he is trying to save C++ from Rust.

> It was proposed by Walter and denied by Stroustroup, probably to save C++. Citation needed. For starters, where is the paper?

Well, there's this list Stroustrup offers, of systems in C++ that he would reject: [0]

[0] https://open-std.org/JTC1/SC22/WG21/docs/papers/2018/p0977r0...

Re: Contracts for C

#50

The author writes that contract_assume invokes undefined behaviour when the assertion fails: #define contract_assume(COND, ...) do { if (!(COND)) unreachable(); } while (false) But this means that the compiler is allowed to e.g. reorder the condition check and never output the message. (Or invoke nasal demons, of course). This doesn't make much sense. I get that you want the compiler to maybe do nothing different or…

There's no assertion required by spec.

To the brain of a compiler writer UB means "the standard doesn't specify what should happen, therefore I can optimize with the assumption UB never happen." I disagree that this is how UB should be interpreted, but this fight is long lost.

With that interpretation of UB, all `unreachable()` means is that the compiler is allowed to optimize as if this point in the code will never be reached. The unreachable macro is standard in C23 but all major compilers provide a way to do it, for all versions of the language.

So if you have a statement like `if (x > 3) unreachable()` that serves as both documentation of the accepted values, as a constraint that the optimizer can understand - if x is an unsigned int, it will optimize with the assumption that the only possible values are 0,1,2.

Of course in a debug build a sane compiler would have `unreachable()` trigger an assert fail, but they're not required to, and in release they most definitely won't do so, so you can't rely on it as a runtime check.

Post reply on HN