Skip to content

Safety

October 6, 2026

As you might have got from the “Civil War” section of this trip report, safety in C++ is a massive theme right now. This has been fuelled in part by a US government report (Product Security Bad Practices | CISA) that essentially said that C++ is unsafe and should be avoided for new projects if safety is important.

To this end, there have been a lot of people striving to make C++ safer to compete with languages that offer more safety guarantees such as Rust. For example, in C++26 there is now the concept of Erroneous Behaviour which is basically Undefined Behaviour except that the behaviour is defined by the implementation, and the implementation is recommended to provide diagnostics when encountering it. Sounds confusing? Reading an uninitialized local variable in C++ before C++26 was deemed undefined behaviour. You could get anything. However in C++26, a read of an uninitialized local variable is now Erroneous Behaviour. This means that compilers MUST define what value that uninitialized local variable has. So by upgrading to C++26, and recompiling your code, reads of uninitialized local variables will no longer be UB, and instead read a compiler defined value. This is obviously a major change, and for most it is a welcome one… However, there are those that disagree… I don’t know how I feel about it either to be quite honest.

I went to a fair few talks around safety while at CppCon. I am quite interested in the topic myself, because it does dovetail with Code Quality which is something I am quite interested in.

Profiles for simplicity and guarantees

Profiles for Simplicity and Guarantees - Bjarne Stroustrup - CppCon 2026

I spoke about this talk tangentially in my “Civil War” section but I think it deserves to actually be talked about. I consider this to be a follow on from Gabriel Dos Reis - Tightening the Screws with C++ Profiles, and as such is all about “Profiles” which is a feature that is aiming for C++29. Profiles are effectively a way of describing the guarantees that you are holding your code to, in the language. You specify the guarantees that you want your code to be held to via attributes, and if your code violates those guarantees, it is an error. Most of these guarantees seem to aim to be verifiable at compile time, which is why I feel like this is essentially standardized warnings as errors. HOWEVER, Bjarne did have this slide

Profile strategy: static analysis, supporting libraries, and run-time checks

If you see the last bullet point, it is quite clear that they are not restricting Profiles to only being a compile time thing… which looks to me like they are competing with contracts, because both profiles and contracts involve run time checks on correctness. In my personal opinion, I don’t see why Profiles and Contracts can’t exist. I am sure they solve the problem in different ways, and provide different trade-offs. Love it or hate it, C++ is all about choice and making sure that the developer can make the best trade-offs for their situation.

Bjarne gave a few examples of the kinds of profiles that he feels could make it to C++29. One was around initialization and ensuring that we guarantee that we are not doing anything wrong with uninitialized objects.

An example initialization profile from Bjarne’s keynote

This was particularly interesting because of Bjarne being against Erroneous Behaviour. I took 2 implications from Bjarne here…

  • He implies that Profiles will do better than Contracts for runtime checking.
  • He implies that Erroneous Behaviour was a mistake because Profiles will catch it anyway.

I am still of the opinion that they are effectively “standardized warnings as errors on steroids”, and I am a big fan of that. They do still have the same challenges as compiler warnings though. For example, we still need to suppress warnings sometimes, and likewise you will likely need to suppress Profile attributes. He talks about how this becomes a problem when implementing a std::vector like class here. He also muses about whether there is a chance that suppression could become too easy. I am of the opinion that suppression should be easy BUT it should be clear and searchable for accountability reasons. If people want to suppress a check, they will, no matter how “hard” it is. This is especially true in a world of AI written code. Difficulty no longer matters. What matters is that it is obvious and can be searched for easily. Accountability is king. C++ style casts are not better than C style casts because they are more verbose. They are better because they stick out like a sore thumb and can easily be searched for.

There is one last part of Bjarne’s keynote that I would like to draw attention to. One question asked why MSVC is not a compiler that supports Profiles. Link. Bjarne quips that “because Profiles are not AI, they have been deprived of resources”. I would like to point out that MSVC is the first and only C++23 compliant compiler at the time of this keynote.

Other sources:

  1. Last 2 features for C++23 coming in 14.52
  2. Last 2 features available in 14.52 preview

Clang and GCC still have features to implement in C++23. So I don’t think we can joke too much about MSVC in regard to unimplemented features… especially when this is a proposed C++29 feature that may or may not make it to C++29.

Towards a complete contract-assertion facility for C++

This was a talk from Timur Doumler who has been heavily involved in the implementation of contracts for at least the last 7 years. One thing to note is that this talk is very much the same as his ACCU on Sea talk (Contract Assertions on Virtual Functions - Timur Doumler - ACCU 2026) but without the philosophy of trying to get people to agree. Contracts are effectively more standardized assertions. Think of them like check and ensure in Unreal Engine except more powerful because you can also put assertions on function signatures. The main elements of this talk were around improvements that were coming to contracts for C++29.

Chief among these improvements is contracts on virtual functions, just like in his ACCU on Sea talk (timestamp). But he also talked about other upcoming features like:

  1. User defined error messages -> so like static_assert, you can provide an error message. No more having to write check(“My error message” && condition) :)
  2. Postcondition captures -> Sometimes you need to refer to the old state of an object to validate a postcondition. e.g. on vector::push_back you might want to assert that the size has increased by 1. To do this the proposal is to allow postconditions to capture old state and refer to that old state during the postcondition.
  3. Labels -> This seems to be a biggie. They basically allow you to group assertions and choose evaluation semantics per group to get more fine-grained control over violation handling across your program. Sounds pretty cool

Type Punning: the joke is on you, pun intended. Fixing UB of reinterpret_cast

This is an update to Lieven’s BeCpp talk (BeCPP Symposium 2026 - Lieven de Cock - Type Punning, the joke is on you, pun intended). Prior to his talk, I was chatting with Lieven about reinterpret_cast. I told him that my understanding was that there were only 2 legitimate (and useful) uses of reinterpret_cast which did not result in UB:

  1. Casting a pointer to a std::intptr_t or std::uintptr_t
  2. Casting anything to an array of char to inspect the bytes

I based my understanding of no.2 on this section of cppreference

The cppreference explanation of type aliasing and examining object representations

Lieven mentioned this conversation in the talk, and confidently said that I was wrong. This is just UB. I believed that you could do this because it is on CppReference, and to some extent CppReference is right. The cast is valid due to an exception carved out in the standard. However, trying to treat the returned pointer as an array of bytes is UB, as Lieven pointed out. So you can do the cast, but not much else that is useful with it. FUN!

Safety in Numbers

I think this is the most fun talk I went to. Not my favourite talk. But certainly the most fun, and most of the fun came from how interactive everyone was. Jason likes to involve the audience a lot and there was A LOT of good engagement which just made it fun… No idea how good it will be as a YouTube video, but being there for it was great craic.

The entire talk was about how we can handle integer arithmetic safely. He talked about things like integer promotion, and overflow. One of the things he talked about was what happens if you compare signed and unsigned numbers. This was a point that I talk about in my talk, so I chimed in and said “that’s a compilation error provided you have warnings as errors enabled”. This prompted a little conversation about the fact that MSVC actually detects A LOT more bugs with C4389 than Clang and GCC do with their equivalents which I was quite surprised about.

There were 3 other interesting titbits that came out of this talk from people in the audience:

  1. If a shared library that enables fast math is loaded, then it can affect other code using the same floating point environment in the process. So even if you intend for your math to execute IEEE-754 compliant floating point operations, depending on the wrong library might change that.
  2. Jason asked the room to put up their hands if they worked on software where if they got their maths wrong (e.g. from issues with not handling arithmetic correctly) then there was a real risk of someone being harmed or killed. More than half of the room put their hands up. That was wild to me. That is a lot of stress haha.
  3. UBSan Minimal Runtime. This is a setting of UBSan that you could enable in production code to catch and log some issues. It is talked about here UndefinedBehaviorSanitizer - Clang. It would be really interesting if we could enable something like this in insiders to catch more stuff…
Last updated on