Hacker Newsnew | past | comments | ask | show | jobs | submit | ahartmetz's commentslogin

In other words, given a need for IPv4, it enables switching to mostly IPv6... seems like transition technology and reality might finally meet because both moved towards the other.

>Nobody in history has been able to write correct C code

Except possibly D.J. Bernstein https://cr.yp.to/ ? Not necessarily all perfect, but designed for extreme simplicity and defense in depth, AFAIU.


It has needed some fixing over the years. errno was one thing. There have been a number of things in that vein, where Bernstein relied upon 1989 C or even K&R semantics and suchlike.

But compared to some other code from the 1990s, it has lasted the test of time quite well.

* https://jdebp.uk/Softwares/djbwares/


He surely also had to face his share of C issues, here advocacy for "Boring C" in 2015,

https://groups.google.com/g/boring-crypto/c/48qa1kWignU/m/o8...


No. I tried his code too.

Nobody.


His apps were some of the worst i've ever seen, usability wise.

As I understand, sacrifices were made to achieve the, for C programs, exceptional security.

Yeah, first time that I hear about it as well. Pretty sure that it is what I'll use next time I need a thermal interface material.

I mean they were possibly going to help anyway or even physically closer. And I imagine that sitting around in the fire department does get boring, something to do occasionally is welcome :)

> I mean they were possibly going to help anyway or even physically closer.

There is a good chance of that.

The fire was in Eygelshoven, Nievelsteenstraat. I don't know how close the nearest fire stations are either side of the border.


Oh great, because in Germany it's exactly the other way around. 110 is police, 112 is firefighters and ambulance.

On the one hand, almost everyone (including C++ fans) agrees that the language is too big. On the other hand, comtracts just formalize an existing and useful concept.

Profiles should (hopefully) rein this in by getting people to start subsetting language features in their codebases

Let's see, they are still a bit of a dream regarding what they wish for, and what current static analysers can achieve, especially the lifetime one.

I was thinking for implementing borrow-checker like rules for C but after I have seen what SMT solver can do I think it is not necessary to constrain the language in this way.

Yeah, the problem with the lifetimes profile vision, is the lack of acknowledgement of how MSVC and clang-tidy have struggled to achieve the Core Guidelines ideas for lifetimes (since 2015), without additional annotations.

MSVC requires SAL and clang has equally added extensions for type annotations.

The WG21 politics killed the Safe C++ proposal with the P3466 paper,

"(Re)affirm design principles for future C++ evolution"

https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p34...

> Do not add a feature that requires viral annotation

However it is quite clear, that without changing language semantics, for the lifetimes profile to be actually useful, as shown by MSVC and clang experience, we would need to have [[profile:lifetime(something)]] in plenty of places.

Not only would that be more verbose than what Rust and Safe C++ proposal, it would still require placing those annotations on the standard library (yet another complaint from the anti-Safe C++ proposal folks), and naturally violate the paper that was voted for as the design principles for future C++ evolution.

However in regards to how to check for C and C++ lifetime issues, at least if the source code is fully available, I have had some good experience with AI tools doing code review, like CoPilot on Visual Studio.

Maybe that is possible way forward, moreso if the code isn't being fully written by humans.

Regarding C specifically, what about having Frama-C's ACSL as some kind of ISO C annex?


Compilers would just ignore the annex and whoever wants to implement it, can already do this. And I also think ACSL is too complex for what is needed and also not well integrated with the rest of the language.

IIRC Rust's borrow checker analysis is more or less a subset of what SMT solving is capable of. It's "just" a question of tradeoffs made with respect to performance, complexity, precision, etc.

It is a really tiny and trivial subset of what model checkers can do. Model checkers can often prove memory safety of entirely unmodified C code. The problem is that this still runs into complexity problems and does not scale to non-toy programs. But this would also really be very far at the other end of the borrow checker that would require rewriting everything into a very specific form a borrow checker accepts.. IMHO a middle ground with some annotations is realistic and would be far more convenient than a borrow checker when supported by good tooling.

> The problem is that this still runs into complexity problems and does not scale to non-toy programs.

Right; that is why Rust's borrow checker was designed to be intraprocedural only. That obviously is a tradeoff of its own: now functions need to be annotated to convey information across function boundaries, and the annotations picked will influence what can and cannot be expressed.

> IMHO a middle ground with some annotations is realistic and would be far more convenient than a borrow checker when supported by good tooling.

I'd be interested in seeing what such a middle ground looks like, particularly in respect to what tradeoffs it makes!


I don't know yet. My current expectation from what I have seen is that lifetime analysis can be done fully automatic for most C code as long as it can be done independently from other program state, i.e. the checker has to reason only about the state of pointers and not also simultaneously about all other variables. I have seen quite promising work on this.

> lifetime analysis can be done fully automatic for most C code as long as it can be done independently from other program state

Is this an interprocedural or intraprocedural analysis?

> I have seen quite promising work on this.

Is this work public? I'm interested in seeing more!


It is interprocedural, but one obviously needs annotations for interfaces to libraries that are linked-in.

One example of a project wich goes in this direction is this work: https://www.sei.cmu.edu/projects/ai-powered-memory-safety-fo...

(I assume the AI is mostly marketing as it is not necessary)


Thanks for the link! That's an interesting approach indeed. If I'm reading the paper [0] correctly the concepts involved look pretty similar to what Rust uses. I think they turn the interprocedural analysis into an intraprocedural one as well by effectively deriving borrowing information from function implementations and attaching that to signatures for use by callers. It's a compatibility hazard, which is why Rust chose to not do the same, but in principle it makes it easier to derive more precise borrowing information.

[0]: https://dl.acm.org/doi/epdf/10.1145/3814943.3816182


They globally derive the borrowing information for all pointers in the whole program by classifying the role of each pointer. If there is a way to do this in a way that makes the program safe, this is computed automatically using a SAT solver.

> They globally derive the borrowing information for all pointers in the whole program by classifying the role of each pointer.

Right; by my reading this is done function-by-function by the constraint generator before passing that information to the solver for verification.


The classification can not be done on the function level. There are two ways, either this is done using AI or using a SAT solver.

The paper explicitly says that if you use an LLM it is prompted function-by-function.

For the SAT solver I think classification can be done function-by-function if you manually drive the solver in the single-function mode, but I think you're more right in that the whole-program mode doesn't actually do that.

I think my misunderstanding stemmed from interpreting the start of section 5.4 and figure 3 as showing that constraint generation occurred strictly before the verifier was invoked and glossing over the bit at the start of section 6 that said that the process basically works the other way around when using the solver to build the p-model.


A borrow checker can do more harm than good in some cases. An arguable example of that is https://fasterthanli.me/articles/a-rust-match-made-in-hell .

Your background is C as I understand it, and C does not really have issues with temporaries as they are known in C++ and Rust.

My understanding:

C compound literals have invariable and relatively long lifetimes, namely to the end of the local block, and to shorten those lifetimes, one has to put the expression with the compound literal in a new, smaller local block. The advantage of those long lifetimes is that lifetimes are typically long enough for it not to cause issues in C. C also does not have RAII.

Both C++ and Rust have varying lifetimes of temporaries and have RAII. Both C++ and Rust have had messes with lifetimes, C++23 changed lifetime rules for the range-initializer expression of range-based for-loops, and Rust changed lifetimes rules in Rust 2024 such that whether a specific piece of Rust code has a deadlock or not, depends on its edition, and editions are generally not specified per-file but per-project.

Temporary lifetime extension can be tricky for both developers and language designers.

But the borrow checker can make it worse in some situations, for it can push developers towards bug prone designs that have greater risks of deadlocks, just to satisfy the borrow checker. The borrow checker also mostly enabled the language designers to go wild with lifetimes, since they did not have to worry as much about UB as long as they were in the not-unsafe subset, so the issues with deadlocks might be worse in practice than if they had been more careful and restrained with lifetimes.

It can also be very subtle whether Rust code has deadlocks or not. One of these Rust programs has a deadlock, the other does not. The difference is the presence and absence of temporary lifetime extension, as per the "{}".

https://play.rust-lang.org/?version=stable&mode=debug&editio...

https://play.rust-lang.org/?version=stable&mode=debug&editio...


I guess this must be the fearless concurrency I am hearing about. /s

In general I understand why people like RAII and the idea of not worrying about pesky details such as resource cleanup is appealing, but the philosophy in C is that the compiler should not do such things behind your back and perhaps this is sometimes valuable. I like this more because things are explicit and visible and I rather want to have tools that tell me that what I do is correct rather than a language that does a lot of things implicitly behind my back (especially if this is correct 99% of times but sometimes surprisingly is not). This is why I am not a fan of C++ nor Rust. Thank you for the nice example illustrating issues in Rust arising from this.


I don't like the "fearless concurrency" motto, because it often gets discussed in isolation of all kinds of concurrency and ways to access resources in systems languages.

It suffices that the resource being accessed concurrently isn't inside in same memory space like shared memory, mapped regions, a database connection, where the Rust type system can do very little to prevent other processes, or conflicting SQL queries without proper transactions, to mess up with the data coherency.


LLM reply?

Yeah an LLM with an unique neural networks biological model designed in Portugal at the edge of Portugal's newly found democracy.

Exactly. Many years ago people used to use C `struct` for objects but then that was formalized as `class`.

C++ "class" is the exact same user-defined type as C++ "struct" but with different defaults for privacy.

But C++ "struct" has many more features than C "struct". Virtual functions aka compiler-generated invisible vtables, constructors (initialization functions) and destructors (automagically called deinitialization functions), the whole templates complex of features...

You can set a "contract evaluation semantic" for contracts. One of them is "observe", which only prints a message on contract violations. With "ignore", nothing at all happens.

I'm pretty sure that housing, cars and food are #1, #2 and #3. Your definition of household spending seems a little unconventional. If pets are household spending, surely so is food for humans?

It was a little inaccurate, you are right:

#2 "after all payments done for yourself/husband"

#1 will be the kids


You can always eat your pets

Well yes, self-declared. China's economic success came after becoming less and less communist in practice. The most (in practice, as observed in real-world communism) communist thing about China is the authoritarian state with a one-party system, which to be sure is better than a full-on one person dictatorship.

Marx viewed capitalism as a necessary precondition for communism. His argument for this was, that communism cannot be built out of poverty. It requires the immense material wealth and industrial capacity that only capitalism can generate. It's probably why the historical communism was such a failure, as it was built out of poverty and not out of abundance.

In this regard, China seems to be closer to Marx' vision of a communist society.


The GDR mostly had the economic preconditions, but one problem or maybe two: its government was basically a puppet of the USSR government, and it was not brought into power by the people. Could have been interesting.

I predict that China will not achieve the communism that Marx had in mind neither. Why? Because I don't believe in predictions about radical changes in highly complex systems. You can make changes, but then you need to watch and see what actually happens instead of sticking with what some guy came up with in his room 150 years ago. Past performance of communism (so-called, but the only one that has ever existed) and current indicators (the autocrats like their power) are stronger predictors than what Marx wrote.

In a possible future if(!) and when AI can do all the work, we might need something like communism, or better extreme social democracy (democracy with massive redistribution), because the alternative is a an economic inequality that makes the Industrial Revolution times in the UK look like 70s Sweden.


Marx doesn't make a prediction here, but merely identifies the necessary precondition for communism, namely, the material abundance generated by capitalism. Fully automated luxury communism cannot emerge without this foundational framework.

However, it is a necessary condition, not a sufficient one. Post-scarcity and automation do not guarantee a transition to communism


If you ignore all the ways in which it isn't close to communism, then it's close to communism. That's fine, but it's not meaningful.

Obviously they want you to use the web interface so they can show you ads and gather more data about you (for ads).

JMAP support turns out to be a strong signal for the business model of an e-mail provider. IMAP they have to have, JMAP is for those who actually care about supporting local client software.


Consider applying for YC's Winter 2027 batch! Applications are open till November 2.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: