HNHacker News
TopNewBestAskShowJobs

safercplusplus

97 karma · joined April 16, 2019

submissionscomments
safercplusplus··on Rust project goals: Immobile types and guaranteed destructors
Hmm, I'm not sure if you're concerned about the "norad"-style run-time checked references I'm imagining or raw references. In either case, the property we (and `Pin<>`) are concerned about is whether an object can be (destructively) moved. You're pointing out a reference derived from a pinning reference essentially inheriting the pinning property. (I.e. the property that the target won't be inappropriately (destructively) moved.)

But with this proposal, the property that the object won't be (destructively) moved is (solely) a property of the object's type. Specifically, it doesn't depend on any property of any reference to the object, and certainly not on any other reference that that reference was derived from, right?

> Any system that replaces `Pin` will probably have to maintain that same property

Maybe any system that compatibly replaces `Pin`. Maybe. But I'm not sure that this proposal is overly concerned with compatibility with `Pin`. That github page explicitly mentions the desire to deprecate `Pin`, right? And like I suggested, if successful enough, it's conceivable that it could end up de facto deprecating Rust's necessarily-trivial-destructive moves in general. Conceivably.

safercplusplus··on Rust project goals: Immobile types and guaranteed destructors
Ok, I guess somebody has to provide the youngsters/uninitiated with some context. What is going on here can be viewed as part of a process of Rust (potentially) incrementally adopting the C++ model, because the Rust model is limited in important ways.

Specifically, Rust's "necessarily-trivial-destructive" moves make it possible for a memory location previously holding a valid object to become invalid without a destructor (or any other handler) being called. Accommodating this possibility resulted in unforeseen (by many) limitations, particularly in the safe subset. (See "the leakpocalypse".) This was partially addressed by the introduction of "pinning" into the Rust language. The posted github page suggests that this sort of pinning is not the ideal approach, and that it is more effective to make the "unmovability" of an object a property of the object's type, rather than a property of the reference to the object, as is the case with the pinning approach.

To be clear, we're talking about Rust-style "necessarily-trivial-destructive" movability here. Traditionally, C++ doesn't really support this sort of movability. That is, even if an object's contents are ("conceptually") moved to a different location, the original source object remains (at its original location) until it is otherwise destroyed (and its destructor called). So in C++, all types are "immovable" in the sense of the posted github page.

The github page notes how these "immovable" types can support self-references completely in the safe subset in a way that pinning can't.

> This unblocks patterns that are currently impossible in safe Rust.

For an idea of some other unblocked patterns, you can consider so-called "norad" pointers [1] (and proxy pointers [2]) in the SaferCPlusPlus library. Analogous to how `RefCell` references can be used to express references that cannot be statically verified to conform to Rust's "aliasing-xor-mutability" restrictions, "norad" pointers can be used to express references that cannot be statically verified to be lifetime safe. This would include, for example, all manner of cyclic references beyond just "self-references".

I think you could implement a version of these norad pointers in Rust that can safely target these immovable types (whose destructor is guaranteed to be called while the object is still in its original location). But note that the C++ implementation uses static inheritance (which Rust does not support) to avoid the noise having to access the target object as "interior" content (like with `RefCell`s).

With the availability of these flexible references, one could imagine immovable types becoming popular in things like games / entity component systems, GUI frameworks, browser engines, and any place where "back pointers" would be convenient. One might even imagine that at some point, types being "immovable" could become the popular default for object types in Rust (among biological and/or non-biological Rust programmers). At which point, people may decide that actually they do want (the contents of) some of their immovable types to be "movable", but they don't necessarily need the object to be destructively movable. So you could imagine the introduction of standard `nondestructive_move()` (and `nondestructive_move_from()`) methods that would be companions of the existing `clone()` (and `clone_from()`) methods. At which point Rust would have counterparts for C++ copy and move constructors (and assignment operators).

In my view, this adoption of the C++ model (potentially) addresses Rust's main limitation. With one consequence being to potentially make automated translation of C and C++ code to (reasonable code in) the safe subset of Rust much more feasible than seems to be currently.

[1] https://github.com/duneroadrunner/SaferCPlusPlus/blob/master...

[2] https://github.com/duneroadrunner/SaferCPlusPlus/blob/master...

safercplusplus··on Memory safety absolutists
Well, there is another safe option for flexible pointers if you can compile as C++ [1]. In C++ you can have non-owning "smart" pointers with run-time-checked lifetimes [2][3]. Importantly, there is no run-time overhead to dereference them. (That is for the "never-null" versions, otherwise there's a null check.) Assignment has additional run-time cost, but pointer assignments are generally much less prevalent in performance-sensitive inner loops than dereferences, right?

And you can statically verify [4] your raw pointers, so that you only need to use the run-time-checked pointers for the more exotic lifetime relationships.

(That said, for the situations where Fil-C acceptably solves your problem, it's probably the more practical, complete and well-supported solution. And since not many seem to be explicitly mentioning it, the recent Fil-C demonstration of memory-safe linux userspace is rather impressive, right? I've heard that IT security is a $100B industry. I'm guessing an inappropriately low proportion of those resources are being invested in Fil-C. :)

[1] https://github.com/duneroadrunner/SaferCPlusPlus-AutoTransla...

[2] https://github.com/duneroadrunner/SaferCPlusPlus#norad-point...

[3] https://github.com/duneroadrunner/SaferCPlusPlus#tnoradproxy...

[4] https://github.com/duneroadrunner/scpptool

safercplusplus··on Cpp2Rust: Translates C++ to safe Rust automatically
If the concern is memory safety, I'd invite comparison with migration to the scpptool-enforced memory-safe subset of C++ [1]. If your C++ code is "idiomatic modern" C++, then the changes required to conform to the safe subset (in an idiomatic way) are often modest, and as demonstrated in the link, often something an LLM can handle for you. Since the safe subset does not impose a universal restriction on mutable aliasing the way Rust does, it doesn't require wrapping everything in `RefCell<>`s or anything like that (unless the objects in question are being shared between threads).

If your C++ code is more "legacy" than "modern", the migration is generally still straightforward, but will often involve additional run-time overhead, like it does with this cpp2rust, but to a lesser degree I think. Objects allocated on the stack can (safely) remain allocated on the stack even when they are the target of pointers. And still, no `RefCell<>` equivalents are required for objects that aren't shared between threads.

[1] https://github.com/duneroadrunner/scpptool/blob/master/READM...

safercplusplus··on Almost Always Unsigned
But are we necessarily limited to native integer types? At least with C++, the type system is powerful enough to support integer replacement types (eg. [0][1]) that don't inherit these issues. (Where, for example, the subtraction of an unsigned from another unsigned returns a value of signed integer type.) Another advantage being the ability to customize the overflow/underflow handling policy per declaration (rather than relying on a compiler flag that applies globally).

[0] https://www.boost.org/doc/libs/develop/libs/safe_numerics/do...

[1] https://github.com/duneroadrunner/SaferCPlusPlus/blob/master...

safercplusplus··on Expanding Project Glasswing
If the source language is C++, another option might be to use AI agents to port to a memory-safe subset of C++ [1]. For the most part, this involves surgical changes and glorified find-and-replace operations. And I'm guessing way fewer tokens :)

If the source language is legacy C, then another option might be (deterministic) transpilation to a memory-safe subset of C++ [2]. The resulting code wouldn't necessarily be performance-optimal, but it can be used for the majority of code that isn't really performance-sensitive.

[1] https://github.com/duneroadrunner/scpp_code_migration [2] https://github.com/duneroadrunner/SaferCPlusPlus-AutoTransla...

safercplusplus··on C constructs that still don't work in C++
You might be interested in the scpptool feature to help convert C code to a subset of C that will also compile as C++ (under clang++ at least) [1]. While many of the necessary modifications are fairly trivial, some of them aren't completely so. For example, C++ does not allow `goto`s that would skip over the declaration/initialization of a variable that would be accessible after the jump. So getting the C code to work as C++ can involve some (automatic) code restructuring.

Another annoying detail is that C++ doesn't seem to like forward references of `enum`s. That is, while

    struct A* a_ptr;
is fine in both C and C++ even before `struct A` has been defined, apparently

    enum A* a_ptr;
is not cool in C++ until after `enum A` has been defined.

One arguable benefit of keeping your C code compatible with (or at least convertible to) C++, is that you can theoretically use scpptool's auto-translation feature as build step to produce memory-safe executables from C code via transpilation to a memory-safe subset of C++.

[1] https://github.com/duneroadrunner/SaferCPlusPlus-AutoTransla...

safercplusplus··on Lib0xc: A set of C standard library-adjacent APIs for safer systems programming
> It's in many cases as simple as renaming a file from .c to .cpp.

That is rather optimistic, but, for example, scpptool has a feature [1] that auto-converts from C to a subset of C that can (hopefully) be compiled with clang++. If the original C source uses C11 extensions, clang++ seems to generally produce warnings rather than compile errors.

> But for writing something from scratch it's better to use Rust.

scpptool attempts to make C++ a more viable option by enforcing a memory and data race safe subset using a similar safety strategy.

[1] https://github.com/duneroadrunner/SaferCPlusPlus-AutoTransla...

safercplusplus··on Bugs Rust won't catch
I think the concern is that the writing may be on the wall for (the current memory-unsafe version of) Coreutils. Despite the bugs and incompatibilities, Canonical seems to have decided that the memory safety of uutils is worth it. And those two downsides, the bugs and incompatibilities, will likely attenuate quickly, compelling the other distros to follow suit in adopting uutils before long.

So the continued popularity of Coreutils might, I think, depend on Coreutil's near-term publicly announced and actual memory safety strategy. As I suggested in my other comment, there are (somewhat nascent) options for memory safety that do not require a rewrite of the code base. (For linux x86_64 platforms, depending on your requirements, that might include the "fanatically compatible" Fil-C.) And given the high profile of Coreutils, there are likely people willing to work with the Coreutils team to help in the deployment of those memory safety options.

safercplusplus··on Bugs Rust won't catch
I don't know if you're aware, but there is a demonstration of wget (a fellow "gnu utility", right?) being auto-translated to a memory-safe subset of C++ [1]. Because the translation essentially does a one-for-one substitution of potentially unsafe C elements with safe C++ counterparts that mirror the behavior, the translation should be much less susceptible to the introduction of new bugs and behaviors in the way a rewrite would be.

With a little cleaning-up of the original code, the code translation ends up being fully automatic and so can be used as a build step to produce (slightly slower) memory-safe executables from the original C source.

[1] https://duneroadrunner.github.io/scpp_articles/PoC_autotrans...

safercplusplus··on Why Objective-C
Interestingly, I recently auto-translated wget from C to a memory-safe subset of C++ [1], which involves the intermediate step of auto-converting from C to the subset of C that will also compile under clang++. You end up with a bunch of clang++ warnings about various things being C11 extensions and not ISO C++ compliant, but it does compile.

[1] https://duneroadrunner.github.io/scpp_articles/PoC_autotrans...

safercplusplus··on Ladybird adopts Rust, with help from AI
And I might suggest that there's the possibility that the C++ code could end up being more cleanly ported to a memory-safe subset of C++. plug: https://github.com/duneroadrunner/scpptool/blob/master/appro...
safercplusplus··on -fbounds-safety: Enforcing bounds safety for C
Plug: In theory you could auto-convert to a memory-safe subset of C++ as a build step. Auto-converted code would have some run-time overhead, but you can mark any performance-sensitive parts of the code to be exempt from conversion. And you get lifetime and type safety too. For full coverage, performance-sensitive parts of the code can be manually converted to the safe subset to minimize overhead. (Interfaces in extern C blocks remain unconverted by default to maintain ABI compatibility.)

[1]: https://duneroadrunner.github.io/scpp_articles/PoC_autotrans...

safercplusplus··on DARPA project for automated translation from C to Rust (2024)
As long as we're plugging our projects, I'll mention the scpptool-enforced memory-safe subset of C++. Fil-C would be generally more practical, more compatible and more expedient, but the scpptool-enforced subset of C++ is more directly comparable to Rust.

scpptool demonstrates enforcement (in C++) of a subset of Rust's static restrictions required to achieve complete memory and data race safety [1]. Probably most notably, the restriction against the aliasing of mutable references is not imposed "universally" the way it is in (Safe) Rust, but instead is only imposed in cases where such aliasing might endanger memory safety.

This is a surprising small set of cases that essentially consists of accesses to methods that can arbitrarily destroy objects owned by dynamic owning pointers or containers (like vectors) while references to the owned contents exist. Because the set is so small, the restriction does not conflict with the vast majority of (lines of) existing C++ code, making migration to the enforced safe subset much easier.

The scpptool-enforced subset also has better support for cyclic and non-hierarchical pointer/references that (unlike Safe Rust) doesn't impose any requirements on how the referenced objects are allocated. This means that, in contrast to Rust, there is a "reasonable" (if not performance optimal) one-to-one mapping from "reasonable" code in the "unsafe subset" of C++ (i.e. traditional C++ code), to the enforced safe subset.

So, relevant to the subject of the post, this permits the scpptool to have a (not yet complete) feature that automatically converts traditional C/C++ code to the safe subset of C++ [2]. (One that is deterministic and doesn't try to just punt the problem to LLMs.)

The problem isn't dedicating public resources to trying to getting LLMs to convert C to Safe Rust after investments in the more traditional approach failed to deliver. The problem is the lack of simultaneous investment in at least the consideration and evaluation of (under-resourced) alternative approaches that have already demonstrated results that the (comparatively well-funded) translate-to-Rust approach thus far hasn't been able to.

[1] https://github.com/duneroadrunner/scpptool/blob/master/appro...

[2] https://github.com/duneroadrunner/SaferCPlusPlus-AutoTransla...

safercplusplus··on Safe C++ proposal is not being continued
> Profiles cannot achieve the same level of safety as Rust

So the claim is that the scpptool approach[1] can, while remaining closer to traditional C++, and not requiring the introduction of new language elements. Since the scpptool-enforced safe subset of C++ is an actual subset of C++, conforming code continues to build with your existing compiler. It just uses an additional static analyzer to check conformance.

For the 90% or whatever of C++ code that is not actually performance sensitive, the associated SaferCPlusPlus library provides drop-in and "one-to-one" safe replacements for unsafe C++ elements (like standard library containers and raw pointers). (For example, if you're worried about potentially invalid vector iterators, you can just replace your std::vector<>s with mse::mstd::vector<>s.) With these elements, most of the safety is enforced in the type system and not reliant on the static analyzer.

Conforming implementations of performance-sensitive code would be more restricted and more reliant on the static analyzer for safety enforcement. And sometimes requires the use of library elements, like "borrowing objects", which may not have analogies in traditional C++. But overall, even high-performance conforming code remains very recognizable C++.

The claim is that the scpptool approach is a straightforward path to full memory (and data race) safety for C++, and the one that requires the least code migration effort. (And again, as an actual subset of existing C++, not technically dependent on standard committees or compiler vendors for its implementation or deployment.)

[1]: https://github.com/duneroadrunner/scpptool/blob/master/appro...

safercplusplus··on Rust: A quest for performant, reliable software [video]
> From what I'm aware of, Rust has poor ergonomics for programs that have non-hierarchical ownership model (ie. not representable by trees)

Yeah, non-hierarchical references don't really lend themselves to static safety enforcement, so the question is what kind of run-time support the language has for non-hierarchical references. But here Rust has a disadvantage in that its moves are (necessarily) trivial and destructive.

For example, the scpptool-enforced memory-safe subset of C++ has non-owning smart pointers that safely support non-hierarchical (and even cyclical) referencing.

They work by wrapping the target object's type in a transparent wrapper that adds a destructor that informs any targeting smart pointers that the object is about to become invalid (or, optionally, any other action that can ensure memory safety). (You can avoid needing to wrap the target object's type by using a "proxy" object.)

Since they're non-owning, these smart pointers don't impose any restrictions on when/where/how they, or their target objects, are allocated, and can be used more-or-less as drop-in replacements for raw pointers.

Unfortunately, this technique can't be duplicated in Rust. One reason being that in Rust, if an object is moved, its original memory location becomes invalid without any destructor/drop function being called. So there's no opportunity to inform any targeting (smart) pointers of the invalidation. So, as you noted, the options in Rust are less optimal. (Not just "ergonomically", but in terms of performance, memory efficiency, and/or correctness checking.) And they're intrusive. They require that the target objects be allocated in certain ways.

Rust's policy of moves being (necessarily) trivial and destructive has some advantages, but it is not required (or arguably even helpful) for achieving "minimal-overhead" memory safety. And it comes with this significant cost in terms of non-hierarchical references.

So it seems to me that, at least in theory, an enforced memory-safe subset of C++, that does not add any requirements regarding moves being trivial or destructive, would be a more natural progression from traditional C++.

safercplusplus··on Undefined Behavior in C and C++ (2024)
Yeah, but C++ now supports "user-defined" annotations which effectively allow you to add the equivalent of any keyword you need, right? (Even if it's not the prettiest syntax.) For example, the scpptool static analyzer supports (and enforces) lifetime annotations with similar meaning to Rust's lifetime annotations.

I believe gcc actually does support `__attribute__ ((pure))` to indicate function purity. (I assume it doesn't actually enforce it, but presumably it theoretically could at some point.)

safercplusplus··on Undefined Behavior in C and C++ (2024)
Right. And of course there are still less-performance-sensitive C/C++ applications (curl, postfix, git, etc.) that could have memory-safe release versions.

But the point is also to dispel the conventional wisdom that C/C++ is necessarily intrinsically unsafe. It's a tradeoff between safety, performance and flexibility/compatibility. And you don't necessarily need to jump to a completely different language to get a different tradeoff.

Fil-C sacrifices some performance for safety and compatibility. The traditional compilers sacrifice some safety for performance and flexibility/compatibility. And scpptool aims to provide the option of sacrificing some flexibility for safety and performance. (Along with the other two tradeoffs available in the same program). The claim is that C++ turns out to be expressive enough to accommodate the various tradeoffs. (Though I'm not saying it's always gonna be pretty :)

safercplusplus··on Undefined Behavior in C and C++ (2024)
A couple of solutions in development (but already usable) that more effectively address UB:

i) "Fil-C is a fanatically compatible memory-safe implementation of C and C++. Lots of software compiles and runs with Fil-C with zero or minimal changes. All memory safety errors are caught as Fil-C panics." "Fil-C only works on Linux/X86_64."

ii) "scpptool is a command line tool to help enforce a memory and data race safe subset of C++. It's designed to work with the SaferCPlusPlus library. It analyzes the specified C++ file(s) and reports places in the code that it cannot verify to be safe. By design, the tool and the library should be able to fully ensure "lifetime", bounds and data race safety." "This tool also has some ability to convert C source files to the memory safe subset of C++ it enforces"

safercplusplus··on The borrowchecker is what I like the least about Rust
Might I suggest that the scpptool-enforced safe subset of C++ has a better solution for such data structures with cyclic or complex reference graphs, which is run-time checked non-owning pointers [1] that impose no restrictions on how or where the target objects are allocated. Unlike indices, they are safe against use-after-destruction, and they don't require the additional level of indirection either.

[1] https://github.com/duneroadrunner/SaferCPlusPlus#norad-point...

safercplusplus··on Memory Safe Languages: Reducing Vulnerabilities in Modern Software Development [pdf]
Makes sense. But maybe the fact that that post is 4 years old serves to bolster the argument for Fil-C's value proposition. However much people may want to move away from their C code bases, the resources it takes to do so in a timely manner are often not so readily available.
safercplusplus··on Memory Safe Languages: Reducing Vulnerabilities in Modern Software Development [pdf]
Preach it brother! :)

Hmm, I take it that the situation is that there are a number of vendors/providers/distros/repos who could be distributing your memory-safe builds, but are currently still distributing unsafe builds?

I wonder if an organization like the Tor project [1] would be more motivated to "officially" distribute a Fil-C build, being that security is the whole point of their product. (I'm talking just their "onion router" [2], not (necessarily) the whole browser.)

I could imagine that once some organizations start officially shipping Fil-C builds, adoption might accelerate.

Also, have you talked to the Ladybird browser people? They seemed to be taking an interested in Fil-C.

[1] https://www.torproject.org/

[2] https://gitlab.torproject.org/tpo/core/tor

safercplusplus··on Pwning the Ladybird Browser
This particular memory vulnerability, as I understand it, was a result of a `ReadonlySpan<>` targeting a resizable vector. A simple technique used by the scpptool-enforced safe subset of C++ to address this situation is to temporarily move the contents of the resizable vector into a non-resizable vector [1] and target the span at the non-resizable vector instead.

Upon destruction, the non-resizable vector will automatically return the contents back to the original resizable vector. (It's somewhat analogous to borrowing a slice in Rust.)

While it wouldn't necessarily prevent you from doing the flawed/buggy thing you were trying to do, it would prevent it from resulting in a memory vulnerability.

[1] https://github.com/duneroadrunner/scpptool#xslta_vector-xslt...

safercplusplus··on Compiling C to Safe Rust, Formalized
Thanks for clarifying. The issue is what code would be rejected for auto-translation, not the correctness of an "accepted" translation (as my comment may have implied).

The point of noting that the example translation quietly does the wrong thing, is that that is the reason that it would have to be ("unconditionally") rejected.

While the paper does suggest that their example translation would be rejected:

> If the original C program further relies on x, our translation will error out

note that precisely determining whether or not the program "further relies on x" statically (at compile/translation-time) is, in general, a "Halting Problem". (I.e. Cannot be reliably done with finite compute resources.) So they would presumably have to be conservative and reject any cases were they cannot prove that the program does not "further rely on x". So it's notable that they choose to use a (provisional) translation that has to be rejected in a significant set of false positive cases.

And at least on initial consideration, it seems to me that an alternative translation could have, for example, used RefCell<>s or whatever and avoided the possibility of "quietly doing the wrong thing". (And thus, depending on your/their requirements, avoid the need for unconditional rejection.) Now, one might be an a situation where they'd want to avoid the run-time overhead and/or potential unreliability of RefCell<>s, but even then it seems to me that their translation choice does not technically avoid either of those things. Their solution allocates on the heap which has at least some theoretical run-time overhead, and could theoretically fail/panic.

Now I'm not concluding here that their choice is not the right one for their undertaking. I'm just suggesting that choosing a (provisional) translation that has to be rejected with significant false positives (because it might quietly do the wrong thing) is at least initially notable. And that there are other solutions out there that demonstrate translation of C to a (high-performance, deterministic) memory-safe language/dialect that don't have the same limitations.

safercplusplus··on Compiling C to Safe Rust, Formalized
And even then, not completely reliably it seems (from Section 2.2):

> The coercions introduced by conversion rules can however lead to subtle semantic differences

The example they give is this C code:

    1 uint8_t x[1] = { 0 };
    2 uint8_t *y = x;
    3 *y = 1;
    4 assert(*x == 1); /* SUCCESS */
getting translated to this (safe) Rust code:

    1 let x: [u8; 1] = [0; 1];
    2 let mut y: Box<[u8]> = Box::new(x);
    3 y[0] = 1;
    4 assert!(x[0] == 1) /* failure */
So the pointer (iterator) targeting an existing (stack-allocated) array declared on line 2 gets translated to an owning pointer/Box) targeting a (heap-allocated) new copy of the array. So if the original code was somehow counting on the fact that the pointer iterator was actually targeting the array it was assigned to, the translated code may (quietly) not behave correctly.

For comparison, the scpptool (my project) auto-translation (to a memory safe subset of C++) feature would translate it to something like:

    1 mse::lh::TNativeArrayReplacement<uint8_t, 1> x = { 0 };
    2 mse::lh::TNativeArrayReplacement<uint8_t, 1>::iterator y = x; // implicit conversion from array to iterator
    3 *y = 1;
    4 assert(*x == 1); /* SUCCESS */ // dereferencing of array supported for compatibility
or if y is subsequently retargeted at another type of array, then line 2 may end up as something like:

    2 mse::TAnyRandomAccessIterator<uint8_t> y = x; // implicit conversion from array to iterator
So the OP project may only be converting C code that is already amenable to being converted to safe Rust. But given the challenge of the problem, I can respect the accomplishment and see some potential utility in it.

edit: added translation for line 2 in an alternate hypothetical situation.

safercplusplus··on Why Safety Profiles Failed
You might consider experimenting with the scpptool-enforced safe subset of C++ (my project). It should be even less disruptive.

[1] https://github.com/duneroadrunner/scpptool

safercplusplus··on Why Safety Profiles Failed
In theory it could be auto-converted to a safe subset of C++ [1]. In theory it could be done at build-time, like the sanitizers.

[1] https://github.com/duneroadrunner/SaferCPlusPlus-AutoTransla...

safercplusplus··on Scpptool – a tool to enforce a memory and data race safe subset of C++
Hey thanks for your support! Committee interest might be nice, but I think what would be most helpful at this point is just additional resources in general, whether as a result of committee interest or otherwise. :)

Here's a feature comparison table that would go on the scpptool retail packaging. (HN supports mono-space font right?):

                               | scpptool |  circle  |   cpp2   |
    -------------------------------------------------------------
    |addresses lifetime safety |     Y    |     Y    |     N    |
    -------------------------------------------------------------
    |addresses iterator safety |     Y    |     Y    |     N    |
    -------------------------------------------------------------
    |supports auto-conversion  |     Y    |     N    | probably |
    |of legacy C++ code        |          |          |  doable  |
    -------------------------------------------------------------
    |reasonable support for    |     Y    |     N    |   not    |
    |cyclic references         |          |          |  safely  |
    -------------------------------------------------------------
    |works with any C++        |     Y    |     N    |     Y    |
    |compiler                  |          |          |          |
    -------------------------------------------------------------
safercplusplus··on Scpptool – a tool to enforce a memory and data race safe subset of C++
So I'll turn my attention toward addressing some of the crashing/reliability that I've been neglecting. If anyone is finding it an issue right now, it may be better in the next few days or weeks. Again, feel free to post an issue in the repository if you're running into something specific you want addressed.
safercplusplus··on Scpptool – a tool to enforce a memory and data race safe subset of C++
You figured out all the letters of the acronym. I'm kinda impressed :) I should probably state it in the documentation, but I made the names kinda comically verbose and ugly to imply that, while these names will always be valid, presumably shorter nicer aliases will be more commonly used. Choosing nice names isn't really part of my skill set. I may be subconsciously hoping the user community will at some point come up with a set of nicer aliases that will just be adopted as de facto standard :)

"rsv" stands for "requires static verification" (to ensure safety). A lot of elements in the library get their safety enforcement via the type system and aren't really dependent on an analyzer like scpptool for their safety. The ones that are generally go in the "rsv" namespace.

I can't remember what "mse" stands for right now. I'm pretty sure the "s" stands for "safe" or "safety". At one point, and possibly still, the idea was to support entities maintaining their own version of the library if they wanted (to completely eliminate dependency risk). In that case one might want to change all the "mse" namespace references to their own namespace name. scpptool is coded to allow you to specify the base namespace of your version of the library.

> There are some other practical issues with the project, such as inconsistent licensing annotations

Any licensing issue is just me being careless/lazy I assume. I don't intend for there to be any restrictions. I think I just tried to make everything original to the project use the boost license, which seems totally permissive to me. If I need to do something to fix the licenses, let me know.

> the fact that it seems to depend on specific Clang versions (and thus will probably bitrot if it stops being maintained)

The only reason there is any dependency on clang version is because the clang libraries keep making breaking changes on successive versions. It used to be really bad, but these days they're generally minor breakages. At this point if someone doesn't want to wait to update the version of clang that scpptool uses, it's pretty much just a matter of doing a search-and-replace for the version number in the build script and makefile, and then fixing whatever annoying thing the new version broke. A lot of times it's them slightly reorganizing the (large) set of clang libraries scpptool needs to build against (which requires modifying the makefile). One of the goals of this project is to be as small of a dependency risk as possible. I think it compares favorably to some of the alternative solutions in that regard.

Page 1 of 2Next →