TE
科技回声
首页24小时热榜最新最佳问答展示工作
GitHubTwitter
首页

科技回声

基于 Next.js 构建的科技新闻平台,提供全球科技新闻和讨论内容。

GitHubTwitter

首页

首页最新最佳问答展示工作

资源链接

HackerNews API原版 HackerNewsNext.js

© 2025 科技回声. 版权所有。

Xr0 Makes C Safer than Rust

49 点作者 akiarie大约 1 年前

15 条评论

eminence32大约 1 年前
While saying &quot;makes C safer than rust&quot; is a good headline to get clicks, I feel like it invites comparisons that aren&#x27;t helpful for advancing this project.<p>Instead, I think something like &quot;Makes C safer than the C code you were using previously&quot; is the better approach.<p>I haven&#x27;t read every detail of this long post, but I do want to highlight something I strongly agree with:<p>&gt; Interface informality is the root cause of unsafety<p>When writing C and C++, I&#x27;ve always felt an uneasy when passing a pointer to a function, because I don&#x27;t really have a way of knowing if this is safe or not.
评论 #39860239 未加载
nneonneo大约 1 年前
Xr0 makes a &quot;limited subset of C89&quot; as safe as Rust, after adding cumbersome function annotations to every function and limiting the types of allocation patterns that can be used. (Also: &quot;Buffer overflows&#x2F;underflows&quot; prevention is not implemented yet. So the Xr0 programs are not yet safer than Rust.)
评论 #39858957 未加载
评论 #39858981 未加载
评论 #39860295 未加载
jchw大约 1 年前
&gt; Is there anything inherently unsafe about multiple (even mutable) references to an object? Has it been shown by some rock-solid argument that such stringent ownership semantics are the only way to guarantee compile-time safety?<p>Nobody is claiming this is the only possible way to make safe programs, as far as I know formal proofs a la seL4, when done correctly, can also prove the absence of essentially any kind of defect. The problem with multiple mutable references is that if you have them, you need some way to validate that across all possible mutable references to a given piece of memory, there are no unsafe concurrent accesses. Rust&#x27;s claim to fame is &quot;fearless concurrency&quot;, and as far as I know borrow checking with one mutable reference exclusive with all other references is the simplest approach to providing concrete data race safety in the face of still having mutable shared state across code. Nothing on this page even mentions data races, and I&#x27;m not sure how you would accomplish safety against data races from this design alone.
animatethrow大约 1 年前
This appears to be more limited than what CBMC[1] (the C Bounded Model Checker) can do. CBMC can do function contracts. CBMC can prove memory safety and even the absence of memory leaks for non-trivial code bases that pass pointers all over the place that must eventually be freed. Applying all the annotations to make this happen though is like 10x the work of getting the program actually running in the first place. CBMC definitely makes C safer than even safe Rust for projects that can invest the time to use it. There is an experimental Rust front end to CBMC called Kani[2] that aims to verify unsafe Rust (thus making unsafe Rust become safe) but it is far from the speed and robustness of the C front end.<p>[1] <a href="https:&#x2F;&#x2F;github.com&#x2F;diffblue&#x2F;cbmc">https:&#x2F;&#x2F;github.com&#x2F;diffblue&#x2F;cbmc</a><p>[2] <a href="https:&#x2F;&#x2F;github.com&#x2F;model-checking&#x2F;kani">https:&#x2F;&#x2F;github.com&#x2F;model-checking&#x2F;kani</a>
okanat大约 1 年前
&gt; This why most attempts to improve on C fail. C is simple and gives the programmer control, and this is why C programmers love and use it.<p>Most C programmers use C because they are forced to use it, by technical limitations like lack of compiler access or human limitations like lack of funding, curiosity or motivation.<p>C unfortunately became the API specification language of the most popular operating systems in the world. Both Unix and Windows world defines their low level system API using C types that strongly ties everybody and every program to C language, C standard library and the preferred compiler of the OS. Even Rust cannot escape it now. However Rust may give us hope &#x2F; motivation and may force people to formally define the interfaces outside C so we can truly get rid of it one day.
评论 #39860676 未加载
throwawayk7h大约 1 年前
&gt; Interface informality is the root cause of unsafety<p>I feel this frequently with C. I would love to formalize pointer use in interfaces. But Xr0&#x27;s proposed syntax is clunky and not backward-compatible.<p><pre><code> void foo(int* x) ~ [ free(x); ]; </code></pre> Yikes... Why not<p><pre><code> &#x2F;&#x2F; &lt;xr0.h&gt; #ifndef __XR0__ #define freed #endif &#x2F;&#x2F; my code: void foo(int* freed x); </code></pre> Boom. Looks clean, easily readable, backward compatible with standard compilers.
评论 #39867934 未加载
Measter大约 1 年前
&gt; Let us ask the question: Is there anything inherently unsafe about multiple (even mutable) references to an object?<p>I think the problem with your example here is that it&#x27;s a bit simplistic. In your example, if we drop the concept of ownership, sure it&#x27;s not unsafe they can both point to the same allocation. But multiple mutable references can absolutely be a big issue. For example:<p><pre><code> pub enum Thing { AA(i32), BB(String), } pub fn foo() { let mut thing = Thing::BB(String::from(&quot;Hello&quot;)); let Thing::BB(str_ref) = &amp;mut thing else {unreachable!()}; bar(&amp;mut thing); println!(&quot;{str_ref}&quot;); } fn bar(_: &amp;mut Thing) { ... }; </code></pre> Without knowing the body of `bar` it&#x27;s not possible to determine whether `foo` is sound. `bar` could change the enum to the `AA` variant, at which point `str_ref` is now pointing at an integer and some padding bytes, not a String. We&#x27;ve violated type safety, and read uninitialized memory both in the enum itself and in the now-dropped heap allocation.
评论 #39864012 未加载
aib大约 1 年前
&quot;[C] is simple but expressive, practical but admitting of elegance (think of some of the pointer arithmetic in K&amp;R); it is small, fast, and portable; it is the lingua franca of programming and the language of languages[...]&quot;<p>How anyone can think pointer arithmetic is elegant is beyond me. Especially when the title mentions a language with algebraic data types and higher order functions. Or even just RAII.<p>I&#x27;m also not sure C is the lingua franca of programming anymore. From my personal experience (and language is strongly tied to geography and culture) people tend to talk about strings and booleans, JSON and other custom types, stacks and heaps. ints and longs have fixed sizes and representations in their minds. (In fact, many C concepts are used erroneously from a strictly-C-language point of view.)<p>This is not to insult C, however, which is elegant in its simplicity (and perhaps The Mother of Modern Programming Languages, if you fancy a majestic title), nor the project, which has a noble goal.
评论 #39868033 未加载
jcranmer大约 1 年前
&gt; Let us ask the question: Is there anything inherently unsafe about multiple (even mutable) references to an object?<p>Yes. The ability to mutate an object necessarily implies the ability to mutate the state of an object to break guarantees. While there are definitely patterns where multiple mutable references to the same object can be safe, it is not inherently safe, and proving safety is far more challenging because you can&#x27;t as easily rely on pre&#x2F;postconditions for lemmas.<p>The particular case that makes the utility of a one-mutable-xor-many-read-only model clear is something I trip over surprisingly frequently in C&#x2F;C++:<p><pre><code> &#x2F;&#x2F; Getting a value gets a pointer to somewhere in the hashtable... Value &amp;V = hash_table[key]; &#x2F;&#x2F; This may cause the hash table to grow, thereby invalidating said pointer... hash_table.insert(key2, value2); &#x2F;&#x2F; ... and now I used it! V = meow; </code></pre> Sure, in a three-line function, it&#x27;s kind of obvious (if you know to be aware of this possibility!), but in a function where the pointer and the use are separated by hundreds of lines of code, it&#x27;s easy to miss that there is a requirement that the hash table not be resized between the two calls. With Rust, the fact that &amp;mut for V means that I can&#x27;t touch the hash table until I&#x27;m finished with V makes it a compiler error.<p>Yeah, there are times when Rust&#x27;s rule here pisses me off and feels too finicky, but it&#x27;s also saved my butt several times. And quite frankly, a lot of the finicky can be worked around by building some solid container libraries to handle the cases where you can guarantee the safety with higher-level abstractions (say append-only data structures).<p>More to the crux of the article however, I&#x27;m not generally impressed with automated theorem proving as a solution to safety. Already from the meat of the article, it seems that this solution is setting you up for using a complex language to specify the interface, which immediately begs the question of how you can be sure the interface is correctly specified.
评论 #39872131 未加载
KerrAvon大约 1 年前
Maybe I&#x27;m missing something, but threadsafety would appear to be entirely unaddressed by Xr0.
评论 #39858878 未加载
评论 #39860176 未加载
norir大约 1 年前
Here is another way to avoid use after free: lint out calls to malloc&#x2F;calloc&#x2F;realloc&#x2F;free in all but a small subset of files. Define a header with an interface with something like:<p><pre><code> void with_bytes(size_t count, void (*cb)(void *bytes); </code></pre> You also may need to write similar wrappers around dependencies that require manual freeing of resources.<p>Programming in this style will force you to think about the life cycle of every allocation and there are ways you can still shoot yourself in the foot. But as long as you avoid storing references in static variables, you will generally avoid memory leaks and use after free when programming in this style.<p>And you can just do this with any c compiler without relying on new dependencies.
评论 #39859019 未加载
dpc_01234大约 1 年前
Maybe I&#x27;m wrong, but...<p>This seems to try to mimic Rust safety rails as impractical annotations. Even if these annotations can express non-trivial cases (which I doubt), they will constrain you for reasons Rust lifetimes can be constraining, you&#x27;ll have to do tons of extra work, with crappy bare-bone programming language, inside an ecosystem where no one gives a crap and that can&#x27;t even agree on a common sane tooling.<p>And then I have no idea from where does it follow that the at thend it will be &quot;Safer than Rust&quot;.<p>How is that better idea than just using a most loved programming language along with a maturing large ecosystem that actually has a culture of building safe and reliable software, using approaches that are not bolted on but built-in?
评论 #39868069 未加载
akira2501大约 1 年前
It&#x27;s just an example.. sure, but:<p><pre><code> int *p = malloc(1); bar(p); free(p); </code></pre> Wouldn&#x27;t the safe way to write that code be to just allocate the value on the stack so it has automatic lifetime managed for you?<p>Excepting that, why are you annotating functions, it&#x27;s the pointer itself that has the use case invariant. Shouldn&#x27;t the type be annotated to declare these semantics instead?
评论 #39858993 未加载
评论 #39858928 未加载
ruslan大约 1 年前
Why using new syntax like ~ [ ]; instead of good old &#x2F;* *&#x2F; or pragmas ?<p>I would prefer something like this:<p><pre><code> void* foo() &#x2F;* return malloc(SIZE) *&#x2F; { void *p = (void*) = malloc(SIZE); bzero(p, SIZE); return p; } </code></pre> It remains compatible with any compiler of choise.*
nneonneo大约 1 年前
Previous discussion: <a href="https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=37536186">https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=37536186</a>