The provenance memory model for C

169 HexDecOctBin 80 6/30/2025, 9:25:14 AM gustedt.wordpress.com ↗

Comments (80)

gavinray · 5h ago
Also of interest to folks looking at this might be TySan, the recently-merged LLVM Type-Based Aliasing sanitizer:

https://clang.llvm.org/docs/TypeSanitizer.html

https://www.phoronix.com/news/LLVM-Merge-TySan-Type-Sanitize...

lioeters · 5h ago
Looks like a code block didn't get closed properly, before this phrase:

> the functions `recip` and `recip⁺` and not equivalent

Several paragraphs after this got swallowed by the code block.

Edit: Oh, I didn't realize the article is by the author of the book, Modern C. I've seen it recommended in many places.

> The C23 edition of Modern C is now available for free download from https://hal.inria.fr/hal-02383654

zmodem · 4h ago
> Looks like a code block didn't get closed properly

This seems to have been fixed now.

perching_aix · 21m ago
I still see it, even after clearing caches, visiting from a separate browser from a separate computer (even a separate network).
johnisgood · 5h ago
It is a great book. I prefer the second edition, not the latest one though with what I call "bloated C".
laqq3 · 52m ago
I'm wondering if you could elaborate? I'd be curious to hear more about "bloated C" and the differences between the 2nd and 3rd edition.
shakabrah · 5h ago
It made immediate sense to me it was Jen once I saw the code samples given
smcameron · 2h ago
Ugh. Are unicode variable names allowed in C now? That's horrific.
OkayPhysicist · 51m ago
Why shouldn't they be? It's not the 00's anymore, Unicode support is universal. You'd have to dust off some truly ancient tech to find something incapable of rendering it.

Source code is for humans, and thus should be written in whatever way makes it easiest to read, write, and understand for humans. If your language doesn't map onto ASCII, then Unicode support improves that goal. If your code is meant to directly implement some physics formula, then using the appropriate unicode characters might make it easier to read (and thus spot transcription errors, something I find far too often in physics simulations).

bigstrat2003 · 21m ago
They shouldn't be precisely because it makes the code harder to read and write when you include non-ASCII characters.
wheybags · 44m ago
Hot take, but I've always felt the world would be better served if mathematicians and physicists would stop using terrible short variable names and use longCamelCaseDescriptiveNames like the rest of us, because paper is cheap, and abbreviations are confusing. I know it's nicer when you're writing by hand, but when you clean up a proof or formula for publishing, would it really be so hard to switch to descriptive names?

I'm a practitioner of neither though, so I can't condemn the practice wholeheartedly as an outsider, but it does make me groan.

nsingh2 · 4m ago
Better served to students and those unfamiliar with the field, but noisy to those familiar. Considering that much of mathematical work is done by hand, it would be a total pain to write out huge variable names every time.

Consider a simple programming example, in C blocks are delimited by `{}`, why not use `block_begin` and `block_end`? Because it's noisy, and it doesn't take much to internalize the meaning of braces.

senbrow · 33m ago
Long names are good for short expressions, but they obfuscate complex ones because the identifiers visually crowd out the operators.

This can be especially difficult if the author is trying to map 1:1 to a complex algorithm in a white paper that uses domain-standard mathematical notation.

The alternative is to break the "full formula" into simpler expression chunks, but then naming those partial expression results descriptively can be even more challenging.

someplaceguy · 35m ago
> using the appropriate unicode characters might make it easier to read

It's probably also a great way to introduce almost undetectable security vulnerabilities by using Unicode characters that look similar to each other but in fact are different.

OkayPhysicist · 16m ago
This would cause your compilation to fail, unless you were deliberately declaring and using near identical symbols. Which would violate the whole "Code is meant to be easily read by humans" thing.
someplaceguy · 12m ago
> unless you were deliberately declaring and using near identical symbols.

Yes, that would probably be one way to do it.

> Which would violate the whole "Code is meant to be easily read by humans" thing.

I'd think someone who's deliberately and sneakily introducing a security vulnerability would want it to be undetectable, rather than easily readable.

mananaysiempre · 2h ago
“Now” as in since C99, twenty-five years ago, yes. (It seemed like a good idea at the time.)
kevincox · 1h ago
Being able to program in languages that don't fit into ASCII is a good idea. Using one-character variable names is a bad idea.
adrianN · 46m ago
Using variable names that are different but render (almost) the same can be a bad idea.
loeg · 21m ago
Math people shouldn't be allowed to write code. It's not the unicode, so much as the extremely terse variable names.
perching_aix · 17m ago
Isn't that basically all C/C++ code? Admittedly I don't have much exposure to it, but it's pretty much a trope in and of itself, along with Java and C# suffering from the opposite problem.

Such a silly issue too, you'd think we'd have come up with some automated wrangling for this, so that those experienced with a codebase can switch over and see super short versions of identifiers, while people new to it all will see the long stuff.

1over137 · 2h ago
Horrific? You might not think so if your (human) language used a different alphabet.
Joker_vD · 1h ago
My language uses Cyrillic and I personally prefer English-based keywords and variable names precisely because they are not words of my (human) language. It introduces an easy and obvious distinction between the machine-oriented and the human-oriented.
eqvinox · 1h ago
Yes but also no. The thing about software is that 90% of it is not culturally bound. If you're writing, say, some tax reporting tool, a grammar reference, or something religious… sure, it makes sense to write that in your language. So, yeah, C should support that.

However, everything else, from spreadsheet software to CAD tools to OS kernels to JavaScript frameworks is universal across cultures and languages. And for better or for worse (I'm not a native English speaker either), the world has gone with English for a lot of code commons.

And the thing with the examples in that post isn't about supporting language diversity, it's math symbols which are noone's native language. And you pretty much can't type them on any keyboard. Which really makes it a rather poor flex IMHO. Did the author reconfigure their keyboard layout for that specific math use case? It can't generically cover "all of math" either. Or did they copy&paste it around? That's just silly.

[…could some of the downvoters explain why they're downvoting?]

OkayPhysicist · 26m ago
When I was doing a lot of Physics simulation in Julia, I had a Vim extension which would just allow me to type something like \gamma, hit tab, and get γ. This was worth the (minimal) hassle, because it made it very easy to spot check formulas. When you're shuffling data around in a loosely-described space like most of web dev, descriptive function and variable names are important because the description of what you're doing and what you're doing it too is the important information, and the actual operations you're taking are typically approximately trivial.

In heavily mathematical contexts, most of those assumptions get turned on their head. Anybody qualified to be modifying a model of electromagnetism is going to be intimately familiar with the language of the formulas: mu for permeability, epsilon for permittivity, etc. With that shared context,

1/(4*π*ε)*(q_electron * q_proton)/r^2 is going to be a lot easier to see, at a glance, as Coulombs law

compared to

1 / (4 * Math.Pi * permitivity_of_free_space)*(charge_electron * charge_proton)/distance_of_separation

Source code, like any other language built for humans, is meant to be read by humans. If those humans have a shared context, utilizing that shared context improves the quality and ease of that communication.

eqvinox · 6m ago
Hrm. Fair point. But will the other humans, even if they have the shared context, also have the ability to type in these symbols, if they want to edit the code? They probably don't have your vim extension…

I guess maybe this is an argument for better UI/UX for symbolic input…

ajross · 1h ago
Little to no source code is written for single (human) language development teams. Sure, everyone would like the ability to write source code in their native language. That's natural.

Literally no one, anywhere, wants to be forced to read source written in a language they can't read (or more specifically in this case: written in glyphs they can't even produce on their keyboard). That idea, for almost everyone, seems "horrific", yeah.

So a lingua franca is a firm requirement for modern software development outside of extremely specific environments (FSB malware authors probably don't care about anyone else reading their cyrillic variable names, etc...). Must it be ASCII-encoded English? No. But that's what the market has picked and most people seem happy enough with it.

OkayPhysicist · 44m ago
> Little to no source code is written for single (human) language development teams.

This is blatantly false. I'd posit that a solid 90% of all source code written is done so by single, co-located teams (a substantial portion of which are teams of 1). That certainly fits the bill for most companies I've worked at.

tialaramex · 6h ago
Presumably this was converted from markdown or similar and the conversion partly failed or the input was broken.

From the PVI section onward it seems to recover, but if the author sees this please fix and re-convert your post.

[Edited, nope, there are more errors further in the text, this needed proper proofreading before it was posted, I can somewhat struggle through because I already know this topic but if this was intended to introduce newcomers it's probably very confusing]

gustedt · 1h ago
The problem is that wordpress changes these things once you edit in some part. I will probably regenerate the whole.
zombot · 6h ago
Does C allow Unicode identifiers now, or is that pseudo code? The code snippets also contain `&`, so something definitely went wrong with the transcoding to HTML.
pjmlp · 5h ago
Besides the sibling comment on C23, it does work fine on GCC.

https://godbolt.org/z/qKejzc1Kb

Whereas clang loudly complains,

https://godbolt.org/z/qWrccWzYW

qsort · 6h ago
Quoting cppreference:

An identifier is an arbitrarily long sequence of digits, underscores, lowercase and uppercase Latin letters, and Unicode characters specified using \u and \U escape notation(since C99), of class XID_Continue(since C23). A valid identifier must begin with a non-digit character (Latin letter, underscore, or Unicode non-digit character(since C99)(until C23), or Unicode character of class XID_Start)(since C23)). Identifiers are case-sensitive (lowercase and uppercase letters are distinct). Every identifier must conform to Normalization Form C.(since C23)

In practice depends on the compiler.

dgrunwald · 5h ago
But the source character set remains implementation-defined, so compilers do not have to directly support unicode names, only the escape notation.

Definitely a questionable choice to throw off readers with unicode weirdness in the very first code example.

qsort · 5h ago
If it were up to me, anything outside the basic character set in a source file would be a syntax error, I'm simply reporting what the spec says.
ncruces · 5h ago
I use unicode for math in comments, and think makes certain complicated formulas far more readable.
kzrdude · 3h ago
I've just been learning pinyin notation, so now i think the variable řₚ should have a value that first goes down a bit and then up.
zelphirkalt · 2h ago
I am not sure it is a good idea to mix such specific phonetic script ideas about diacritic marks with the behavior of the program over time. Even considering the shape, it does not align with the idea of first down a little, then up a lot.
guipsp · 4h ago
What a "basic character set" is depends on locale
account42 · 3h ago
Anything except US-ASCII in source code outside comments and string constants should be a syntax error.
guipsp · 2h ago
You are aware other languages exist? Some of which don't even use the Latin script?
Y_Y · 2h ago
What; like APL‽
Y_Y · 2h ago
Implementation-defined until C99, explicitly possible via UCNs aince c99, possible with explicit encoding since C23, but literals are still implementation defined.
unwind · 5h ago
I can't even view the post, I just get some kind of content management system-like with the page as JSON or something, in pink-on-white. I'm super confused. :|

The answer to your question seems to (still) be "no".

Joker_vD · 1h ago
> Here the term "same representation and alignment" covers for example the possibility to look at [...] one would be a structure and the other would be another structure that sits at the beginning of the first.

Does it? It is quite simple for a struct A that has struct B as its first member to have radically different alignment:

    struct B { char x; };

    struct A { struct B b; long long y; };
Also, accidentally coinciding pointers are nothing "rare" because all objects are allowed to be treated as 1-element arrays: so any pointer to an e.g. struct field is also a pointer one-past the previous field of this struct; also, malloc() allocations easily may produce "touching" objects. So thanks for allowing implementations to not have padding between almost every two objects, I guess.
layer8 · 7m ago
This is about the representation and alignment of the pointer object, not about the object being pointed to. And C requires struct pointer types to all have the same representation and alignment. This is generally necessary due to the possibility of having pointers to opaque struct declarations in a translation unit.

Regarding your second point, if I understand the model correctly, there is only an ambiguity in pointer provenance if the adjacent objects are independent "storage instances", i.e. separately malloc'ed objects or separate variables on the stack — not between fields of the same struct.

eqvinox · 2h ago
Using the "register" storage class feels really alien for C code written in 2025…
b0a04gl · 3h ago
provenance model basically turns memory back into a typed value. finally malloc wont just be a dumb number generator, it'll act more like a capability issuer. and access is not 'is this address in range' anymore, but “does this pointer have valid provenance”. way more deterministic, decouples gcc -wall
HexDecOctBin · 2h ago
Will this create more nasal demons? I always disable strict aliasing, and it's not clear to me after reading the whole article whether provenance is about making sane code illegal, or making previously illegal sane code legal.
jcranmer · 2h ago
All C compilers have some notion of pointer provenance embedded in them, and this is true going back decades.

The problem is that the documented definitions of pointer provenance (which generally amount to "you must somehow have a data dependency from the original object definition (e.g., malloc)") aren't really upheld by the optimizer, and the effective definition of the optimizer is generally internally inconsistent because people don't think about side effects of pointer-to-integer conversion. The one-past-the-end pointer being equal (but of different provenance) to a different object is a particular vexatious case.

The definition given in TS6010 is generally the closest you'll get to a formal description of the behavior that optimizers are already generally following, except for cases that are clearly agreed to be bugs. The biggest problem is that it makes pointer-to-int an operation with side effects that need to be preserved, and compilers today generally fail to preserve those side effects (especially when pointer-to-int conversion happens more as an implicit operation).

The practical effect of provenance--that you can't magic a pointer to an object out of thin air--has always been true. This is largely trying to clarify what it means to actually magic a pointer out of thin air; it's not a perfect answer, but it's the best answer anyone's come up with to date.

Diggsey · 1h ago
It's standardizing the contract between the programmer and the compiler.

Previously a lot of C code was non-portable because it relied on behaviour that wasn't defined as part of the standard. If you compiled it with the wrong compiler or the wrong flags you might get miscompilations.

The provenance memory model draws a line in the sand and says "all C code on this side of the line should behave in this well defined way". Any optimizations implemented by compiler authors which would miscompile code on that side of the line would need to be disabled.

Assuming the authors of the model have done a good job, the impact on compiler optimizations should be minimized whilst making as much existing C code fall on the "right" side of the line as possible.

For new C code it provides programmers a way to write useful code that is also portable, since we now have a line that we can all hopefully agree on.

layer8 · 2h ago
This is basically a formalization of the general understanding one already had when reading the C standard thoroughly 25 years ago. At least I was nodding along throughout the article. It cleans up the parts where the standard was too imprecise and handwavy.
briandw · 4h ago
The code blocks are very difficult to read on this page. I had ChatGPT O3 rewrite this in a more accessible format. https://chatgpt.com/share/68629096-0624-8005-846f-7c0d655061...
cenobyte · 2h ago
So much better. Thank you!
jvanderbot · 5h ago
I love Rust, but I miss C. If C can be updated to make it generally socially acceptable for new projects, I'd happily go back for some decent subset of things I do. However, there's a lot of anxiety and even angst around using C in production code.
flohofwoe · 4h ago
> to make it generally socially acceptable for new projects...

Or better yet, don't let 'social pressure' influence your choice of programming language ;)

If your workplace has a clear rule to not use memory-unsafe languages for production code that's a different matter of course. But nothing can stop you from writing C code as a hobby - C99 and later is a very enjoyable and fun language.

Y_Y · 2h ago
I don't want to summon WB, but honest-to-god, D is a good middle ground here.
TimorousBestie · 3h ago
> Or better yet, don't let 'social pressure' influence your choice of programming language ;)

It’s hard. Programming is a social discipline, and the more people who work in a language, the more love it gets.

spauldo · 1h ago
If you're on UNIX or working in the embedded space, C is still everywhere and gets lots of love. C tends to get lots of libraries anyway because everything can FFI to it.
xxs · 4h ago
I was about the reply no amount of pressure can tell me how to program. C was totally fine for esp32
bnferguson · 4h ago
Feels like Zig is starting to fill that role in some ways. Fewer sharp edges and a bit more safety than C, more modern approach, and even interops really well with C (even being possible to mix the two). Know a couple Rust devs that have said it seems to scratch that C itch while being more modern.

Of course it's still really nice to just have C itself being updated into something that's nicer to work with and easier to write safely, but Zig seems to be a decent other option.

purplesyringa · 59m ago
How close are Zig's safety guarantees to Rust's? Honest question; I don't follow Zig development. I can't take C seriously because it hasn't even bothered to define provenance until now, but as far as I'm aware, Zig doesn't even try to touch these topics.

Does Zig document the precise mechanics of noalias? Does it provide a mechanism for controllably exposing or not exposing provenance of a pointer? Does it specify the provenance ABA problem in atomics on compare-exchange somehow or is that undefined? Are there any plans to make allocation optimizations sound? (This is still a problem even in Rust land; you can write a program that is guaranteed to exhibit OOM according to the language spec, but LLVM outputs code that doesn't OOM.) Does it at least have a sanitizer like Miri to make sure UB (e.g. data races, type confusion, or aliasing problems) is absent?

If the answer to most of the above is "Zig doesn't care", why do people even consider it better than C?

dnautics · 16m ago
safety-wise, zig is better than C because if you don't do "easily flaggable things"[0] it doesn't have buffer overruns (including protection in the case of sentinel strings), or null pointer exceptions. Where this lies on the spectrum of "C to Rust" is a matter of judgement, but if I'm not mistaken it is easily a majority of memory-safety related CVEs. There's also no UB in debug, test, or release-safe. Note: you can opt-out of release-safe on a function-by-function basis. IIUC noalias is safety checked in debug, test, and release-safe.

In a sibling comment, I mentioned a proof of concept I did that if I had the time to complete/do correctly, it should give you near-rust-level checking on memory safety, plus automatically flags sites where you need to inspect the code. At the point where you are using MIRI, you're already bringing extra stuff into rust, so in practice zig + zig-clr could be the equivalent of the result of "what if you moved borrow checking from rustc into miri"

[0] type erasure, or using "known dangerous types, like c pointers, or non-slice multipointers".

pjmlp · 3h ago
As usual the remark that much of the Zig's safety over C, has been present since the late 1970's in languages like Modula-2, Object Pascal and Ada, but sadly they didn't born with curly brackets, nor brought a free OS to the uni party.
dnautics · 3h ago
(self-promotion) in principle one should be able to implement a fairly mature pointer provenance checker for zig, without changing the language. A basic proof of concept (don't use this, branches and loops have not been implemented yet):

https://www.youtube.com/watch?v=ZY_Z-aGbYm8

mikewarot · 5h ago
If you can stomach the occasional Begin and End, and a far less confusing pointer syntax, Pascal might be the language for you. Free Pascal has some great string handling, so you never have to worry about allocating and freeing them, and they can store gigabytes of text, even Unicode. ;-)
jvanderbot · 5h ago
If my fellow devs cringe at C, imagine their reaction to Pascal
mikewarot · 4h ago
C has all the things to hate in a programming language

  CaSe Sensitivity
  Weird pointer syntax
  Lack of a separate assignment token
  Null terminated strings
  Macros - the evil scourge of the universe
On the plus side, it's installed everywhere, and it's not indent sensitive
zelphirkalt · 2h ago
You mean "mere string replacement macros, instead of hygienic macros", of course : )
ioasuncvinvaer · 3h ago
Except for null terminated strings these don't seem like mayor issues to me. Can you elaborate?
jvanderbot · 4h ago
At this point, you're talking to someone who isn't here
1718627440 · 3h ago
> Lack of a separate assignment token

What does that mean?

kbolino · 2h ago
Assignment is = which is too close to equality == and thus has been the source of bugs in the past, especially since C treats assignment as an expression and coerces lots of non-boolean values to true/false wherever a condition is expected (if, while, for). Most compilers warn about this at least nowadays.
tgv · 5h ago
Or try Ada.
modeless · 3h ago
Fil-C is a modified version of Clang that makes C and C++ memory safe. It supports things you wouldn't expect to work like signal handling or setjmp/longjmp. It can compile real C projects like SQLite and OpenSSL with minimal to no changes, today. https://github.com/pizlonator/llvm-project-deluge/blob/delug...
uecker · 1h ago
Do you really love Rust, or do you feel pressured to say so?
grg0 · 52m ago
He grew up in a very stringent household. Everybody was writing Rust and he was like, "damn, I wish I could write C."
cenobyte · 2h ago
Please fix the code in your post.