2025

Improving Code Safety in C++26: Managers and Dangling References -- Bartlomiej Filipek

codesafety2-filipek.pngIn this blog post, we’ll explore ways to improve the safety of a simple configuration manager. We’ll handle common pitfalls like dangling references and excessive stack usage. Additionally, we’ll see how C++26 helps enforce safer coding practices with stricter diagnostics and improved handling of large objects.

Improving Code Safety in C++26: Managers and Dangling References

by Bartlomiej Filipek

From the article:

Step 1: The Buggy Implementation 
 
Below is a simple example of a manager object that stores various configs in a map and provides a method to retrieve them. When a requested configuration isn’t found, the code attempts to return a default certificate:

codesafety-filipek.png

Do you see a potential error in this code?

. . .

At first glance, the code looks harmless. However, if the requested entry isn’t found, the function returns a reference to a temporary std::vector. Once the function exits, that temporary is destroyed—leaving you with a dangling reference and undefined behavior.

Inside STL: Waiting for a std::atomic to change, part 2 -- Raymond Chen

RaymondChen_5in-150x150.jpgLast time, we looked at how the Microsoft C++ standard library implements wait and notify_* for std::atomic<std::shared_ptr<T>>. Today, we’ll look at the other library that (as of this writing) implements std::atomic<std::shared_ptr<T>>: libstdc++.

Inside STL: Waiting for a std::atomic<std::shared_ptr<T>> to change, part 2

by Raymond Chen

From the article:

The first thing to note is that the traditional “wait for a value to change” mechanism on unix is the futex, but futexes (futexen?) are limited to 4-byte values, which is insufficient for a 64-bit pointer, much less the two pointers inside a shared_ptr.

At this point, I will refer you to learn about how libstdc++ implements waits on atomic values, particularly the section on how it handles types that do not fit in a __platform_wait_t. The remainder of this discussion will treat that as an already-solved problem and focus on the shared pointer part.

Okay, back to atomic<shared_ptr<T>>::wait():

// atomic<shared_ptr<T>>::wait
void
wait(value_type __old,
     memory_order __o = memory_order_seq_cst) const noexcept
{
    _M_impl.wait(std::move(__old), __o);
}

When you wait on a shared_ptr, the work is done by _Sp_atomic::wait:

// _Sp_atomic<shared_ptr<T>>::wait
void
wait(value_type __old, memory_order __o) const noexcept
{
    auto __pi = _M_refcount.lock(memory_order_acquire);
    if (_M_ptr == __old._M_ptr && __pi == __old._M_refcount._M_pi)
      _M_refcount._M_wait_unlock(__o);
    else
      _M_refcount.unlock(memory_order_relaxed);
}

Workshops for Everyone -- ACCU Conference

The ACCU conference has a range of workshops, including online options, this year:

Workshops for Everyone

by ACCU Conference

From the article:

See all the offerings, from Jason Turner, Nicolai Josuttis, Robert Seacord, Gail Ollis, Mateusz Pusz, Phil Nash and Mike Shah.

Making C++ Safer -- Greg Law

Should you start new projects in C++, these days? Is language safety an issue for you? What can be done, today?

Making C++ Safer

by Greg Law

From the article:

I believe that over time C++ will become a lot safer, maybe even some kind of ‘safe’. Competition is good: Clang was the best thing to happen to GCC, and Rust might turn out to be the best thing to happen to C++. That journey has already begun, with proposals for the evolution of the language including Contracts and Profiles, and simply changing some of the defaults in C++26. While the language custodians work to make the language itself safer, what can you do today?

 

Inside STL: Waiting for a std::atomic to change, part 1 -- Raymond Chen

RaymondChen_5in-150x150.jpgWhen using std::atomic<std::shared_ptr<T>>, the C++ standard defines a "change" as a modification to either the stored pointer or the control block pointer. However, since atomic wait mechanisms typically track only a single memory address, the Microsoft implementation handles this limitation by using a timeout-based polling strategy to detect changes in the control block.

Inside STL: Waiting for a std::atomic<std::shared_ptr<T>> to change, part 1

by Raymond Chen

From the article:

Like other std::atomic specializations, std::atomic<std::shared_ptr<T>> supports the wait and notify_* methods for waiting for the value to change and reporting that the value has changed. The definition of “changed” in the C++ language specification is that the value has changed if either the stored pointer or the control block pointer has changed. A shared pointer is implemented as a pair of pointers, but Wait­On­Address can wait on at most 8 bytes, and unix futexes can wait on only four bytes, so how does this work?¹

The Microsoft implementation waits for the stored pointer to change, and the notify_* methods signal the stored pointer. But wait, this fails to detect the case where the stored pointer stays the same and only the control block changes.

std::atomic<std::shared_ptr<int>> p =
    std::make_shared<int>(42);

void change_control_block()
{
    auto old = p.load();
    auto empty = std::shared_ptr<int>();

    // Replace with an indulgent shared pointer
    // with the same stored pointer.
    p.store({ empty, old.get() });
    p.notify_all();
}

void wait_for_change()
{
    auto old = p.load();
    p.wait(old);
}

C++26: A Placeholder with No Name -- Sandor Dargo

SANDOR_DARGO_ROUND.JPGIn this post, we are going to discuss a core language feature proposed by Corentin Jabot and Micheal Park in P2169R4. With the new standard we get a cool unnamed placeholder.

C++26: A Placeholder with No Name

by Sandor Dargo

From the article:

By convention, when we have a variable whose value we don’t want to use or care about, we often name it _. The problem is that with higher warning levels (-Wunused-variable), our compilation might fail because _ is unused.
int foo() {
return 42;
}

auto _ = foo();
/* error: unused variable '_' [-Werror,-Wunused-variable] */

To avoid this problem, we must mark it [[maybe_unused]].

 

PVS-Studio 7.35: MISRA C 2023 support, Qt Creator 15 plugin, and more

PVS-Studio 7.35 has been released. Support for the MISRA C standard, the plugin for Qt Creator 15.x, modified file analysis in Visual Studio, and that's not all.

PVS-Studio 7.35: MISRA C 2023 support, Qt Creator 15 plugin, and more

by Vladislav Bogdanov

From the article:

We've begun work to expand the PVS-Studio's coverage of the MISRA C standard. With the release of 7.35, the first eight diagnostic rules have already been implemented, and more are on the way. The full list of implemented rules is provided below. We plan to cover at least 85% of MISRA C and support the latest version of MISRA C 2023.

 

Write More C++ Code Thanks to constexpr -- Andreas Fertig

me.pngSince its introduction, the constexpr keyword in C++ has steadily evolved with each new standard, becoming an increasingly powerful tool for compile-time computation and optimization. In this article, I’ll share a real-world example of how constexpr helped optimize memory usage and improve performance for an embedded system project, showcasing its potential to transform how we approach C++ programming.

Write More C++ Code Thanks to constexpr

by Andreas Fertig

From the article:

Since the keyword constexpr and its behavior got included in C++, it has been improved in each and every new standard of the language.

I'm a big fan of constexpr and am not alone. Jason Turner is also very vocal, having coined the term "constexpr all the things".

Well, demonstrating the powers of constexpr is nonetheless something difficult. I know that from my training classes and various consulting contracts. Today, I'd like to share a story from back in time when a customer hired me to consult. They did develop an embedded system and ran out of memory. Not during run-time, but before. The features they wanted to put in the chip were too big in code size and somewhat RAM.

Initial constexpr-free example

They used a class I've seen a couple of times in embedded systems with some variations. A string brings its memory picky-back. 

 

 

Reverse Iterations -- Coral Kashri

c-senioreas-v9.pngSometimes, we all need a way to iterate over a container in the opposite direction. There are several ways to reverse-iterate a container, and in this article, we’ll explore them.

Reverse Iterations

by Coral Kashri

From the article:

Probably the simplest way, taken from C is to iterate using an index location:
for (int64_t index = ssize(container); index >= 0; --index) {
    // do something with `container[index]`
}
This way is highly not recommended as it might lead to infinite loops if done incorrectly (for example by using uint64_t or size_t for the index type), and you can find more issues with this way in some previous articles about iterators in this blog.

C++26: user-generated static_assert messages -- Sandor Dargo

SANDOR_DARGO_ROUND.JPGstatic_assert further evolves with C++26. Our tool for compile-time assertion will support user-generated error messages. As such, we’ll be able to reuse messages as well as enrich them with information available at compile-time making diagnostics easier to read.

C++26: user-generated static_assert messages

by Sandor Dargo

From the article:

Our first quest into the world of C++26 was about =delete with an optional error message, which improves the readability of the source code and potentially the error messages. In this next part of our journey, we will continue to focus on readability improvements, particularly those for error messages.

With C++26 and the acceptance of P2741R3, we are getting better error messages for static_assert. Compile time assertions were introduced in C++11 with a mandatory message. Since C++17, the message is only optional. And with C++26, static_assert evolves further and the message can be a constant expression instead of an unevaluated string. In other words, it can have some dynamic elements.

This was not the first attempt to make such a feature part of C++, but back in 2014, when something similar was proposed, C++ didn’t have enough compile-time programming capabilities to make this easily implementable.

Why is this change useful?

Before looking at some concrete examples of utilisation, let’s dig into the motivations behind this feature.

Obviously, we want better error messages. C++ is infamous for its horrendous error logs when the compilation fails. Even though we must admit that it’s more and more just a legacy, the situation improved a lot over the course of the years. In any case, it was mostly template-related error messages that were behind the biggest issues.

While compile-time assertions with their custom messages already meant an improvement, user-generated diagnostic messages will further improve the situation.

But that’s not the only motivation. Sometimes you don’t want different, or better messages. You just want the same message in several assertions without having to duplicate it. Without this change, the following piece of code doesn’t compile: