An example when we don’t need std::shared_ptr in C++

In the previous example, independent components needed shared ownership of cached objects. For a TCP session, however, we can compare two designs: multiple callbacks keeping the session alive through std::shared_ptr, or a single owning coroutine using std::unique_ptr and structured concurrency. In the second design, reading and writing still run concurrently, but the owner waits for both operations to stop before destroying the session. No shared ownership or reference counting is needed.

(more…)

An example when we really need std::shared_ptr in C++

A practical example of using std::shared_ptr, std::weak_ptr, and a custom deleter to implement a thread-safe object cache. Multiple independent components can share the same object by retrieving it by name. When the last owner releases its shared_ptr, the custom deleter automatically removes the corresponding entry from the cache and destroys the object.

This example demonstrates how shared ownership simplifies object lifetime management without requiring centralized tracking of individual users.

(more…)

An example of how GCC 13 optimizes std::memcpy

C++ code below demonstrates how GCC 13 optimizes std::memcpy and a temporary std::array:

#include <array>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <new>
#include <type_traits>

template <class T>
T* startLifetimeAs(void* const buffer)
{
    std::array<std::byte, sizeof(T)> representation;

    // Preserve the bytes before placement new ends the previous lifetime.
    std::memcpy(representation.data(), buffer, representation.size());

    // Start the lifetime of T in the original storage.
    T* const result = ::new (buffer) T;

    // Initialize the object representation of the newly created T.
    std::memcpy(result, representation.data(), representation.size());

    return result;
}
(more…)

How Placement New Ends an Object’s Lifetime

Below I provided an example demonstrating how placement new creates multiple objects within the same byte storage. Non-overlapping objects can coexist, while constructing an overlapping object ends the lifetime of the previously existing object. Accessing an object after its lifetime has ended causes undefined behavior.

#include <cstddef>
#include <cstdint>
#include <iostream>
#include <new>

struct Packet final
{
    std::uint64_t Data[4];
};

struct A final
{
    std::uint32_t First;
    std::uint32_t Second;
};

struct B final
{
    std::uint32_t First;
    std::uint32_t Second;
};

struct C final
{
    std::uint32_t Value;
};
(more…)

Examples of Undefined Behavior Related to Type Accessibility in C++

From C++ standard:

Attempting to read or modify the stored value through any other type results in undefined behavior.

Any other type means type accessablity:

The first basic example illustrating this principle:

#include <cstdint>

std::uint32_t toInt(float value)
{
    auto* p = reinterpret_cast<std::uint32_t*>(&value); // The cast itself is permitted.
    return *p; // Undefined behavior: accesses a float object through a std::uint32_t glvalue.
}
(more…)

Violating strict aliasing with reinterpret_cast in C++

The first simple example:

#include <bit>
#include <cstdint>
#include <iomanip>
#include <iostream>

std::uint32_t badBits(const float value)
{
  // const prevents writes, but reading a float through a uint32_t pointer
  // still violates the strict-aliasing rule.
  const auto* bits = reinterpret_cast<const std::uint32_t*>(&value);
  return *bits; // Undefined behavior.
}

std::uint32_t goodBits(const float value)
{
  // std::bit_cast copies the object representation without violating
  // strict-aliasing or object-lifetime rules.
  return std::bit_cast<std::uint32_t>(value);
}

int main()
{
  constexpr float value = 1.0F;

  std::cout << std::hex
      << "bad:  0x" << badBits(value) << '\n'
      << "good: 0x" << goodBits(value) << '\n';
}
(more…)

Show RDP connections with credentials in PowerShell

Get-ChildItem `
'HKCU:\Software\Microsoft\Terminal Server Client\Servers' |
ForEach-Object {
    $p = Get-ItemProperty $_.PSPath

    [PSCustomObject]@{
        Server   = $_.PSChildName
        Username = $p.UsernameHint
    }
}
(more…)

Override one virtual function multiple times in C++

The code below does not compile in C++:

template <class Result, class... Params>
class Slot
{
public:

    virtual Result operator()(Params ... args) = 0;
};
(more…)

Debugging Credential Provider with Visual Studio 2022 Remote Debugger

I installed Remote Tools for Visual Studio 2022 and run:

(more…)

Investigating Credential Providers on Windows

I registered a sample Credential Provider with the following .reg file:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\{5fd3d285-0dd9-4362-8855-e0abaacd4af6}]
@="SampleV2CredentialProvider"

[HKEY_CLASSES_ROOT\CLSID\{5fd3d285-0dd9-4362-8855-e0abaacd4af6}]
@="SampleV2CredentialProvider"

[HKEY_CLASSES_ROOT\CLSID\{5fd3d285-0dd9-4362-8855-e0abaacd4af6}\InprocServer32]
@="SampleV2CredentialProvider.dll"
"ThreadingModel"="Apartment"
(more…)