Bug Reports: Memory Leak in VC++ PPL and ASAN support in MFC

Today, I just filed 2 bug reports on Visual C++: Memory Leaks in VC++ PPL’s parallel_for_each() reported by Deleaker and MFC support in Address Sanitizer. The latter is having linkage issue of duplicate symbols of new/delete operators that exists in both MFC and Clang ASAN. I need your help to upvote these 2 bug reports so that Microsoft won’t unilaterally close without resolving them.

Thank you in advance!

Update: I have 1 more bug report: MFC SDI and MDI application crash in WinMain in ASAN in debug mode. Please kindly upvote it as well.

Direct2D Tutorial Part 1: RenderTarget

Introduction

Direct2D is introduced to phase out the dated GDI+ in 2009 and is supported on Windows 7 or newer. This is the first in an introductory Direct2D tutorial series. In this tutorial, we are going to take a look at various different RenderTarget. Think RenderTarget as a canvas to draw on. We focus on 4 Render Target types listed below. Each for its own purpose.

  • HWND Render Target
  • Device Context (DC) Render Target
  • Bitmap Render Target
  • Windows Imaging Component (WIC) Render Target

HWND Render Target

The first Render Target is HWND based. Before we can use Direct2D, 2 namespace must be introduced: D2D1 and Microsoft::WRL for accessing Direct2D class and ComPtr (a smart pointer for COM object)

using namespace D2D1;
using namespace Microsoft::WRL;

To simplify the factory creation and access, the factories are put in FactorySingleton.

class FactorySingleton
{
public:
    static ComPtr<ID2D1Factory> GetGraphicsFactory();
    static ComPtr<IWICImagingFactory> GetImageFactory();
    static void DestroyImageFactory();
private:
    static ComPtr<ID2D1Factory> m_GraphicsFactory;
    static ComPtr<IWICImagingFactory> m_ImageFactory;
};

GetGraphicsFactory() will create the graphics factory if its pointer is nullptr.

ComPtr<ID2D1Factory> FactorySingleton::GetGraphicsFactory()
{
    if (!m_GraphicsFactory)
    {
        D2D1_FACTORY_OPTIONS fo = {};

#ifdef DEBUG
        fo.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION;
#endif

        HR(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED,
            fo,
            m_GraphicsFactory.GetAddressOf()));

    }
    return m_GraphicsFactory;
}

We’ll use MFC to demostrate the Direct2D code. A MFC dialog class to hold ID2D1HwndRenderTarget object named as m_Target and 3 functions.

class CD2DHwndRTDlg : public CDialogEx
{
    ComPtr<ID2D1HwndRenderTarget> m_Target;

    void CreateDeviceResources();
    void CreateDeviceIndependentResources();
    void Draw();
};

In this first tutorial, we will not use any resource and therefore shall not create any, so CreateDeviceResources() and CreateDeviceIndependentResources() shall be empty. Draw() clears the dialog window to a corn blue colour.

void CD2DHwndRTDlg::CreateDeviceResources()
{
}

void CD2DHwndRTDlg::CreateDeviceIndependentResources()
{
}

void CD2DHwndRTDlg::Draw()
{
    m_Target->Clear(ColorF(0.26f, 0.56f, 0.87f));
}

All the drawing occurs in the overidden OnPaint(), if m_Target is nullptr, we create it with the graphics factory’s CreateHwndRenderTarget(). After m_Target is created, CreateDeviceResources() shall be called to create the device dependent resource that is tied to the m_Target. As mentioned before, in this tutorial, we do not have any resource. Before any drawing is done, we first checked whether our window is occluded(meaning blocked by other window), if it is, drawing is skipped. All drawing must be done between the BeginDraw() and EndDraw(). When EndDraw() returns D2DERR_RECREATE_TARGET, we reset m_Target to nullptr and called Invalidate() which will pump WM_PAINT message which in turns cause the OnPaint() to be called again. When m_Target is found to be nullptr, it will be created once more.

void CD2DHwndRTDlg::OnPaint()
{
    // unrelated code generated from VC++ wizard not shown
    CDialogEx::OnPaint();

    if (!m_Target)
    {
        CRect rc;
        GetClientRect(rc);

        D2D1_SIZE_U size = D2D1::SizeU(
            rc.right - rc.left,
            rc.bottom - rc.top
        );

        HR(FactorySingleton::GetGraphicsFactory()->CreateHwndRenderTarget(
            RenderTargetProperties(),
            HwndRenderTargetProperties(GetSafeHwnd(), size),
            m_Target.ReleaseAndGetAddressOf()));

        CreateDeviceResources();
    }

    if (!(D2D1_WINDOW_STATE_OCCLUDED & m_Target->CheckWindowState()))
    {
        m_Target->BeginDraw();

        Draw();

        if (D2DERR_RECREATE_TARGET == m_Target->EndDraw())
        {
            m_Target.Reset();
            Invalidate();
        }
    }
}

This is our corn blue window.

BlankCornBlueDialog

Device Context (DC) Render Target

Next, we take a look at Device Context Render Target. Reader may ask since we have HWND Render Target, why do we need a DC Render Target? That is a very good question. HWND Render Target does not render correctly on a scrollable window while DC Render Target has no problem rendering while the window is scrolling. Other than that, there is no reason to use a DC RT over a HWND RT. This time, m_Target is a generic ID2D1DCRenderTarget object.

class CD2DDeviceContextRTDlg : public CDialogEx
{
    ComPtr<ID2D1DCRenderTarget> m_Target;

    void CreateDeviceResources();
    void CreateDeviceIndependentResources();
    void Draw();
};

DC RT is created with CreateDCRenderTarget() of the graphics factory. Before any drawing is done on a DC RT, a valid DC must be bound with BindDC(). DC is not checked to be occluded since generic m_Target does not provide the CheckWindowState().

void CD2DDeviceContextRTDlg::OnPaint()
{
    //CDialogEx::OnPaint();
    if (!m_Target)
    {
        // Create a pixel format and initial its format
        // and alphaMode fields.
        D2D1_PIXEL_FORMAT pixelFormat = D2D1::PixelFormat(
            DXGI_FORMAT_B8G8R8A8_UNORM,
            D2D1_ALPHA_MODE_PREMULTIPLIED
        );

        D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties();
        props.pixelFormat = pixelFormat;

        HR(FactorySingleton::GetGraphicsFactory()->CreateDCRenderTarget(&props,
            m_Target.ReleaseAndGetAddressOf()));

        CreateDeviceResources();
    }

    CPaintDC dc(this);
    CRect rc;
    GetClientRect(rc);
    m_Target->BindDC(dc.GetSafeHdc(), &rc);

    m_Target->BeginDraw();

    Draw();

    if (D2DERR_RECREATE_TARGET == m_Target->EndDraw())
    {
        m_Target.Reset();
        Invalidate();
    }
}

Bitmap Render Target

We can use Bitmap RT to provide double buffering to DC RT. m_BmpTarget is additional RT (which will do all the drawing) while m_Target blit its bitmap to the window.

class CD2DBmpRTDlg : public CDialogEx
{
    ComPtr<ID2D1DCRenderTarget> m_Target;
    ComPtr<ID2D1BitmapRenderTarget> m_BmpTarget;

    void CreateDeviceResources();
    void CreateDeviceIndependentResources();
    void Draw();
};

m_BmpTarget‘s Clear() must be called between its BeginDraw() and EndDraw().

void CD2DBmpRTDlg::Draw()
{
	m_BmpTarget->BeginDraw();
	m_BmpTarget->Clear(ColorF(0.26f, 0.56f, 0.87f));
	m_BmpTarget->EndDraw();
}

Before m_Target creates m_BmpTarget, its DC must be bound with BindDC(). GetBitmap is called on m_BmpTarget to get its internal bitmap for m_Target to DrawBitmap() onto the window.

void CD2DBmpRTDlg::OnPaint()
{
    //CDialogEx::OnPaint();
    CRect rc;
    GetClientRect(rc);
    CPaintDC dc(this);

    if (!m_Target)
    {
        // Create a pixel format and initial its format
        // and alphaMode fields.
        D2D1_PIXEL_FORMAT pixelFormat = D2D1::PixelFormat(
            DXGI_FORMAT_B8G8R8A8_UNORM,
            D2D1_ALPHA_MODE_PREMULTIPLIED
        );

        D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties();
        props.pixelFormat = pixelFormat;

        HR(FactorySingleton::GetGraphicsFactory()->CreateDCRenderTarget(&props,
            m_Target.ReleaseAndGetAddressOf()));

        m_Target->BindDC(dc.GetSafeHdc(), &rc);

        HR(m_Target->CreateCompatibleRenderTarget(m_BmpTarget.ReleaseAndGetAddressOf()));

        CreateDeviceResources();
    }

    Draw();

    ComPtr<ID2D1Bitmap> bitmap;
    m_BmpTarget->GetBitmap(bitmap.GetAddressOf());

    m_Target->BindDC(dc.GetSafeHdc(), &rc);

    m_Target->BeginDraw();

    m_Target->DrawBitmap(bitmap.Get());

    if (D2DERR_RECREATE_TARGET == m_Target->EndDraw())
    {
        m_Target.Reset();
        Invalidate();
    }
}

Windows Imaging Component (WIC) Render Target

Lastly, we have Windows Imaging Component Bitmap Render Target for saving the drawing onto a image format such as JPEG and PNG. In FactorySingleton, we have GetImageFactory() which creates the image factory when it is checked to be nullptr. We also have DestroyImageFactory() to destroy the image factory.

ComPtr<IWICImagingFactory> FactorySingleton::GetImageFactory()
{
    if (!m_ImageFactory)
    {
        CreateInstance(CLSID_WICImagingFactory, m_ImageFactory);
    }
    return m_ImageFactory;
}

void FactorySingleton::DestroyImageFactory()
{
    if (m_ImageFactory)
    {
        m_ImageFactory.Reset();
    }
}

WIC needs COM runtime, so we have to call CoInitialize() and CoUninitialize() to initialize and deinitialize COM runtime. Because image factory is a singleton which in turn is a global variable: it may be destroyed only after COM runtime is deinitialized. To prevent that, we call DestroyImageFactory() before CoUninitialize() to make sure the global COM object(image factory) is destroyed first.

CD2DWicRTApp::CD2DWicRTApp()
{
	HR(CoInitialize(nullptr));
}

CD2DWicRTApp::~CD2DWicRTApp()
{
	FactorySingleton::DestroyImageFactory();
	CoUninitialize();
}

In the dialog class, m_Target is a generic ID2D1RenderTarget object which would be backed by the WIC bitmap. This time, we are not going to paint the window but onto the WIC bitmap via m_Target and save the image on disk with SaveAs().

class CD2DWicRTDlg : public CDialogEx
{
    ComPtr<ID2D1RenderTarget> m_Target;
    ComPtr<IWICBitmap> m_WicBitmap; // WIC for above RT

    void CreateDeviceResources();
    void CreateDeviceIndependentResources();
    void Draw();

    void PaintAndSaveImage(PCWSTR filename);

    void SaveAs(ComPtr<IWICBitmap>& bitmap, PCWSTR filename);
};

We call PaintAndSaveImage() with a path to the new image file.

BOOL CD2DWicRTDlg::OnInitDialog()
{
    // irrelevant code not displayed
    // TODO: Add extra initialization here
    PaintAndSaveImage(L"C:\\temp\\sample.PNG");

    return TRUE; 
}

m_WicBitmap is created with image factory through CreateBitmap() and then m_Target is created from graphics factory’s CreateWicBitmapRenderTarget() with m_WicBitmap as its first argument. After drawing is done, SaveAs() is called to save the image.

void CD2DWicRTDlg::PaintAndSaveImage(PCWSTR filename)
{
    CRect rc;
    GetClientRect(rc);

    if (!m_Target)
    {
        // Create a pixel format and initial its format
        // and alphaMode fields.
        D2D1_PIXEL_FORMAT pixelFormat = D2D1::PixelFormat(
            DXGI_FORMAT_B8G8R8A8_UNORM,
            D2D1_ALPHA_MODE_PREMULTIPLIED
        );

        D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties();
        props.pixelFormat = pixelFormat;

        HR(FactorySingleton::GetImageFactory()->CreateBitmap(rc.right, rc.bottom,
            GUID_WICPixelFormat32bppPBGRA,
            WICBitmapCacheOnLoad,
            m_WicBitmap.ReleaseAndGetAddressOf()));

        HR(FactorySingleton::GetGraphicsFactory()->CreateWicBitmapRenderTarget(m_WicBitmap.Get(),
            RenderTargetProperties(), m_Target.ReleaseAndGetAddressOf()));

        CreateDeviceResources();
    }

    m_Target->BeginDraw();

    Draw();

    if (D2DERR_RECREATE_TARGET == m_Target->EndDraw())
    {
        m_Target.Reset();
        Invalidate();
    }
    else
    {
        SaveAs(m_WicBitmap, filename);
    }
}

void CD2DWicRTDlg::SaveAs(ComPtr<IWICBitmap>& bitmap, PCWSTR filename)
{
    CString filename_lower = filename;
    filename_lower = filename_lower.MakeLower();
    CString ext = filename_lower.Right(4);
    GUID guid = GUID_ContainerFormatPng;
    if (ext == L".png")
        guid = GUID_ContainerFormatPng;
    else if (ext == L".jpg")
        guid = GUID_ContainerFormatJpeg;

    ext = filename_lower.Right(5);
    if (ext == L".jpeg" || ext == L".jpg+")
        guid = GUID_ContainerFormatJpeg;

    ComPtr<IStream> file;

    HR(SHCreateStreamOnFileEx(filename,
        STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE,
        FILE_ATTRIBUTE_NORMAL,
        TRUE, // create
        nullptr, // template
        file.GetAddressOf()));

    ComPtr<IWICBitmapEncoder> encoder;

    HR(FactorySingleton::GetImageFactory()->CreateEncoder(guid,
        nullptr, // vendor
        encoder.GetAddressOf()));

    HR(encoder->Initialize(file.Get(), WICBitmapEncoderNoCache));

    ComPtr<IWICBitmapFrameEncode> frame;
    ComPtr<IPropertyBag2> properties;

    HR(encoder->CreateNewFrame(frame.GetAddressOf(), properties.GetAddressOf()));

    HR(frame->Initialize(properties.Get()));

    UINT width, height;
    HR(bitmap->GetSize(&width, &height));
    HR(frame->SetSize(width, height));

    GUID pixelFormat;
    HR(bitmap->GetPixelFormat(&pixelFormat));

    auto negotiated = pixelFormat;
    HR(frame->SetPixelFormat(&negotiated));

    HR(frame->WriteSource(bitmap.Get(), nullptr));

    HR(frame->Commit());
    HR(encoder->Commit());
}

We have reached the end of the first tutorial. I hope you have a clear understanding of what each Render Target type is used for. The example code is hosted on Direct2D tutorials.

 

C/C++: Allocate Variable-size Arrays on the Stack

C language provides the alloca function to allocate arbitrary size array on the stack. After the function returns or the scope ends, the stack memory is automatically reclaimed back(popped back) without the developer having to deallocate it explicitly and thereafter is unsafe to access it again from another function. The below code shows allocating fixed size and arbitrary size stack memory. While arbitrary size stack memory has flexibility, care has to be taken that not too much is allocated to exhaust all the available stack memory(default is 1MB), especially the developer is writing a library and has no control over how his library is used. For instance, his library may be used in a worker thread with only 10KB of stack memory.

// allocate fixed-length memory on the stack:
int buf[10];

// allocate arbitrary-length memory on the stack:
char* buf = (char*)alloca(10 * sizeof(int));

Starting from C++17, it is possible to specify a memory buffer to be used for containers in the std::pmr namespace. PMR stands for Polymorphic Memory Resources. Though containers in std and std::pmr namespace have similar interface, they are not interchangeable. To use std::pmr containers such as string and vector, C++17 has to be enabled first in the Visual C++ project properties. See screenshot below.

enable_cpp17

The std::pmr::string example allocates a buffer with alloca and passes it to monotonic_buffer_resource which is then passed into the std::pmr::string.

#include <iostream>
#include <string>
#include <memory_resource>

// allocate some memory on the stack:
char* buf = (char*)alloca(200);

std::pmr::monotonic_buffer_resource pool{ buf, 200 };
std::pmr::string str{ &pool };

str = "just a non-SSO string";

std::cout << str << std::endl;

The std::pmr::vector example allocates on the stack and construct monotonic_buffer_resource, with that buffer. The std::pmr::vector takes in the monotonic_buffer_resource.

#include <iostream>
#include <vector>
#include <string>
#include <memory_resource>

// allocate some memory on the stack:
char* buf = (char*)alloca(200000);

// and use it as initial memory pool for a vector:
std::pmr::monotonic_buffer_resource pool{ buf, 200000 };
std::pmr::vector<std::string> coll{ &pool };

for (int i = 0; i < 1000; ++i) {
    coll.emplace_back("just a non-SSO string");
}

What happens when the PMR container runs out of the assigned memory buffer? It shall allocate on the heap or the upstream memory resource specified at its constructor.

C# stackalloc

Interestingly, C# also has a similar feature such as the stackalloc keyword that allocate on the stack as opposed to the new keyword which allocates on the heap through the Garbage Collector(GC).

int length = 3;
Span<int> numbers = stackalloc int[length];
for (var i = 0; i < length; i++)
{
    numbers[i] = i;
}

Reference

 

Address Sanitizer in Visual C++

In this blog, I’ll demonstrate on how to utilize Address Sanitizer (ASan) in Visual C++ to check for memory problems. MSVC team ported the Clang ASan to the Windows platform in 2019 and since it is still at the experimental stage, be sure to expect kinks to be ironed out.

Before using Address Sanitizer in Visual C++, it has to be installed by the Visual Studio Installer. Check the “C++ AddressSanitizer (Experimental)” checkbox and then click the Modify button.

enable_asan_installer

After installing ASan, be sure to add this path to your PATH environment variable so that your executable can find the clang_rt.asan_dynamic-i386.dll

C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.26.28801\bin\Hostx64\x86

EnvironmentVariables

Add the environment variable by clicking the “New” button and paste the path in the new row and click Ok.

EditEnvironmentVariables

Enable the AddressSanitizer in your C++ project properties.

enable_asan_vc

At this time of writing, ASan supports only Release and 32-bit build. x64 support is in the works and is coming soon. As a matter of fact, x64 support is available on Visual C++ Update 16.7 Preview 1.

x64_not_supported

debug_not_supported

Console application

Add the 2 lines of code below to the main function to trigger the ASan detection of memory access violation and console application would terminate to show the line number of the source code that causes this crash. As the console output is verbose, it shall not be shown here.

int* arr = new int[10];
arr[10] = 1;

MFC application

Attempt to build MFC application with ASan causes these multiple defined symbols linker errors because new and delete operators are defined in MFC and Clang library at the same time. I have no good way of resolving this linkage errors. I have filed a bug report, please help upvote it else Microsoft will unilaterally close it without resolving it.

2>uafxcw.lib(afxmem.obj) : error LNK2005: "void * __cdecl operator new(unsigned int)" (??2@YAPAXI@Z) already defined in clang_rt.asan_cxx-i386.lib(asan_new_delete.cc.obj)
2>uafxcw.lib(afxmem.obj) : error LNK2005: "void __cdecl operator delete(void *)" (??3@YAXPAX@Z) already defined in clang_rt.asan_cxx-i386.lib(asan_new_delete.cc.obj)
2>uafxcw.lib(afxmem.obj) : error LNK2005: "void * __cdecl operator new[](unsigned int)" (??_U@YAPAXI@Z) already defined in clang_rt.asan_cxx-i386.lib(asan_new_delete.cc.obj)
2>uafxcw.lib(afxmem.obj) : error LNK2005: "void __cdecl operator delete[](void *)" (??_V@YAXPAX@Z) already defined in clang_rt.asan_cxx-i386.lib(asan_new_delete.cc.obj)
2>D:\TextPerfect\Source\Release\SDIScratchPad2.exe : fatal error LNK1169: one or more multiply defined symbols found

Win32 OpenGL application

Lastly, I tried ASan on a Win32 OpenGL application. To make sure ASan works as intended, I added the 2 offending lines. After I made sure ASan detection works, I remove those 2 lines.

int* arr = new int[10];
arr[10] = 1;

To see the ASan output in a GUI application which does not have a console, you have use Visual Studio to debug your Release build application. The ASan output will be shown in the output pane of Visual Studio. But you will notice no line number of the offending line is revealed. To fix that, let’s add debug information to your Release build.

add_debug_info

This step is automatically done for the earlier console application. As long as the OpenGL application runs to completion without crashing, it means ASan is not triggered on memory access violations.

Reference

 

C++ Empty Class and Function

More than 10 years ago, when I first debugged my Boost code, I stepped into empty class and empty function. At that time, I was wondering what empty class and function devoid of any code is good for. In this tip, I am going to use a simple endian swap example to demostrate the use of empty class and function in templates.

First we define 2 class Same and Different to indicate same or different endianness. Why can’t we use true or false? You ask. true and false are of the same boolean type. As a template type, they are the same, as far as the C++ compiler is concerned.

class Same
{};

class Different
{};

What is size of a empty class?

std::cout << "sizeof(Same) is " << sizeof(Same) << std::endl;
std::cout << "sizeof(Different) is " << sizeof(Different) << std::endl;

Visual C++, G++ and Clang all gave the size of one. Why size of one? Because C++ memory allocator has trouble instantiating zero-sized object.

sizeof(Same) is 1
sizeof(Different) is 1

Next, we have our dummy PacketWriter which takes in one template type, SameEndianType and has one Write function that takes a short integer and swap it if the SameEndianType is Different. We have 2 Swap functions where there is nothing to be done for same endianness. C++ compiler will optimize away the call to empty Swap() in release build. There is no need to give a name to the second parameter of Swap() because it is not going to be used inside Swap() anyway.

// Dummy PacketWriter
template<typename SameEndianType>
class PacketWriter
{
    typedef SameEndianType endian_type;
public:
    void Write(short n)
    {
        std::cout << "Before swapping, n=" << n << std::endl;
        Swap(n, endian_type());
        std::cout << "After swapping, n=" << n << std::endl;
    }
private:
    void Swap(short& n, Same)
    {
    }
    void Swap(short& n, Different)
    {
        short upper = (n & 0xff) << 8;
        short lower = (n & 0xff00) >> 8;
        n = upper | lower;
    }
};

The code below test 2 PacketWriter objects of Same and Different endian.

std::cout << "Create PacketWriter<Same> to write a short int" << std::endl;
PacketWriter<Same> w;
w.Write(256);

std::cout << "Create PacketWriter<Different> to write a short int" << std::endl;
PacketWriter<Different> w2;
w2.Write(256);

The output of the test program is as expected: PacketWriter<Same> do not swap the short integer whereas PacketWriter<Different> do actually swap it. The upside of this templated endianness is endianness check before swap is eliminated at runtime but the downside is you cannot change the behaviour dynamically during runtime.

Create PacketWriter<Same> to write a short int
Before swapping, n=256
After swapping, n=256

Create PacketWriter<Different> to write a short int
Before swapping, n=256
After swapping, n=1

That’s all for today! Hope you like this tip! The demo code is hosted at Github.

C++23: Mutable string_view

In the upcoming C++23, the mutable string_view proposal is under review for inclusion in the next Standard Library. As we all know the current immutable string_view has two members, a const pointer to a constant char array and a constant length whereas in the mutable sibling, both members are modifiable. Let me illustrate with a simple situation where this mutable class comes handy.

Consider this XML snippet and imagine a mutable string_view pointing to the contents of Name attribute.

<Company Name="Ben &amp; Jerry" />

This is the contents of Name attribute before unescaping &amp; to &.

Ben &amp; Jerry

This is the contents of Name attribute after unescaping. It became a shorter text, so the char array and length in string_view has to be changed. This poses a problem for current immutable string_view but not the mutable one for this scenario.

Ben & Jerry

What if the mutable string_view is set to a longer text? Then memory has to be allocated on the heap. The important question is who is in charge of deallocating this memory? Mutable string_view or developer? A heap allocation can always be tracked and deallocated by the object before it goes out of scope! Some might argue this goes against the zero-cost abstraction principle. Or that responsibility can fall on the developer; to do that, the address in the member pointer shall be checked to fall within that boundary of the whole XML string, if it isn’t, it must be allocated outside and shall be deallocated manually. This is fiercely debated issue from the camp who see this manual mechanism as a unsafe hotbed for memory leaks.

The main draw to mutable string_view is it can yield considerable gains in performance under the assumption that most mutable string_view objects remain unchanged or even it does mutate, it is to a shorter text than to a longer one. Longer text case should be an occasional occurence but it can be dealt with deftly when circumstance calls for it. The C++ developers, around the world, look forward and welcome mutable string_view in its Standard Library.

chandler_carruth

“Mutable string_view is what string_view should have been in the 1st place!” – Chandler Carruth

herb_sutter

“Zero-cost abstraction is the guiding principle behind the design of mutable string_view and it should be the direction going forward with future proposals!” – Herb Sutter

andrei

“Mutable string_view will undeniably help bring forth other innovations like mutable span, just like what typelist did for tuple and CTRE.” – Andrei Alexandrescu

scott_meyers

“That’s it! I am coming out of C++ retirement to teach mutable string_view” – Scott Meyers

scott_meyers

“Mutable string_view should be properly named as enough_rope_to_hang_yourself!” – Bjarne Stroustrup

Before anyone mount a serious commentary to this blog post, take a good look at the posting date!

Disclaimer: None of the abovementioned persons made the testimonials listed in this blog. The testimonials are fully made up.

You may like previous year’s April Fool post: C++23: fullptr to replace nullptr.

Deleaker Review

What keeps a C++ developer awake at night?

A nagging question at the back of his subconsciousness is “Does my application have a memory leak?”. Continual memory leaks can be detrimental to long-running programs and eventually, the system runs out of memory and is stopped in its operation. Detection and elimination of memory leak should be of the highest priority to every application developer.

Visual C++ has, for a long time, a bunch of macros that enable reports of memory leaks via _CrtDumpMemoryLeaks(). This approach has a number of drawbacks.

  • The macros have to be manually added at the top of every C++ source file. The application code has to be instrumented with _CrtXxx family of functions to assist and fine-tune the detection. This is needless and disruptive development work where time could have been spent fixing more issues.
  • There has to be a way to hide those Microsoft-specific macros when compiling on a non-Microsoft platform.
  • The macros are incompatible with a library that overloads their ‘new’ operator. For instance, Microsoft’s GDI+.
  • The report, those macros enables, often identifies false positives or memory leak that occurred in official Microsoft or third-party libraries that the developer is either not interested in or helpless to fix. Needless to say, the reliability of the report leaves much to be desired.

If a C++ developer is anyone like me, looking for a hassle-free solution that just works, period. In this review, we shall put the Deleaker profiler to the test and see if it delivers on its goal. Deleaker is a memory leak detection tool that can be used as a standalone tool or as an IDE extension. Deleaker uses hooks and does not modify the code of a program: code execution speed remains almost the same. Deleaker doesn’t require a program to be rebuilt. All that Deleaker needs is debug information to locate the source of leaks. It supports both 32-bit and 64-bit code. Its full feature list is below.

  • Deleaker is a standalone proprietary memory leak detection tool and is often used as the Visual C++ extension.
  • Detects memory, GDI and WinAPI handle leaks and easily integrates with IDE. Supported IDEs include
    • All versions of Visual Studio since 2005
    • Qt Creator
    • Delphi
    • C++ Builder
    • RAD Studio
  • The standalone version debugs the application to show the current allocation of objects.
  • Detect leaks in .NET languages such as C# and C++/CLI.
  • Supports all 32 – bit as well as 64 – bit system and fully integrated with Visual Studio.
  • Generates rich reports and exports the final outcome to XML.

C++ Application Profiling

A C++ MFC Direct3D slideshow application is the first profiling test. This application takes photos and songs to make into a slideshow. Before Deleaker can be used as a profiler in a debugging session, it has to be enabled beforehand from the extension menu because not in every debugging session, the developer is interested in finding out the memory leaks.

enable_deleaker

Before the debugging begins, a dialog prompt shows up to select the allocation types to be monitored.

alloc_types

The MFC slideshow application screenshot is shown.

mandy_app_mfc

After the testing is done and the application is closed, Deleaker shall collect all the allocation information including their call-stack. Even if the application being debugged is terminated via the debugger stop command, Deleaker prompts the user whether to collect the allocation information. The hit count (in red rectangle) column shows the number of times the exact source code line has been responsible for allocation. As the reader can see from the Deleaker screenshot, many leaks are from the Microsoft Parallel Patterns Library (PPL). Prior to this test, I ran a Text Rendering application on Deleaker whose test result shows no leaks. That result was, unfortunately, a false negative because the testing is not thorough enough: the Gaussian Blur Text Shadow feature that utilizes PPL, is not activated. That shows profiling is only as good as the test coverage.

ppl_leaks

Double-clicking on any line shall highlight the exact line in the source code editor where the allocation is done. The application is found to have memory leaks through some raw pointer which is resolved by using a smart pointer to do the lifetime management. The lesson here to the C++ developers is raw pointer use is to be avoided at all costs.

C# and C++ Hybrid Application Profiling

For the second test, a .NET WPF application is used. As everyone knows .NET is an automatic garbage collection based platform and all memory allocations are managed by the GC. So what constitutes a memory leak? How does Deleaker define a memory leak on .NET? This question is put to Deleaker developer, Artem Razin. His reply is as follows.

Artem: There is a special profiler mode in Deleaker for .NET. A snapshot contains live objects in such case. Leaks in .NET can happen if object count is growing again and again unexpectedly.

The Deleaker tutorial mentioned There is one important thing related to debugging .NET code. Deleaker is able to find both managed and unmanaged leaks in .NET code: if .NET code calls DLLs written in C++, Deleaker is able to find such leaks. Nevertheless, don’t forget to enable unmanaged code debugging in project settings. Without that, Deleaker can’t attach to started processes. Cool, now .NET developer can kill two birds with one stone. To test the .NET memory leak detection capabilities of Deleaker, C# version of the same slideshow is used. The UI is implemented in Windows Presentation Foundation (WPF) this time instead of MFC, the bulk of the slideshow work is in the same engine now encapsulated in one C DLL for C# to call via Platform-Invoke. The results show no .NET leaks, only C++ memory leaks were found through the use of raw pointers in the C dll. The lesson is reinforced that raw pointer use must be totally discouraged and the smart pointer should be the preferred way to do resource management. In the slideshow source code, almost all allocations are tracked and managed by smart pointers like STL’s shared_ptr/unique_ptr and WRL ComPtr but as all best efforts go, use of some raw pointer regrettably slipped through.

mp3_mem_leak

The WPF slideshow application screenshot is shown.

mandy_app_wpf

Deleaker provides the feature of taking snapshots and comparing them to track the source of growing allocation. One complaint is that when there are many allocations, it can take quite awhile for a snapshot to complete meanwhile the slideshow came to a complete halt. This might not be acceptable to time-critical/time-sensitive software (like communication-based or low-latency). The pros and cons of Deleaker are summarized below.

Pros

  • No instrumenting or modifying of code to enable memory detection. In other words, it just works!
  • Real-time memory usage graph to help visualize memory growth over time.
  • Snapshots comparison to find growing memory leaks.
  • Easily find the exact line of source code that allocates (leaked) memory with one double click.
  • Entire callstack is available for every memory leak to see who are its callers and how it happens.
  • Tight integration with the IDEs.
  • Works on other popular IDEs such as Qt Creator and C++ Builder
  • Supports Delphi and .NET languages such as C# and C++/CLI
  • Can detect memory leaks in managed and unmanaged code simultaneously from the same application.
  • Can also detect Win32 resource handle leaks.

Cons

  • Taking a snapshot can take some time when there are many allocations.
  • It only works on the Microsoft Windows platform.

Regarding the last con, it can be overcome: rather then debugging memory issue on MacOSX/Unix/Linux, that is if the C++ code is truly cross-platform, it can always be run and profiled under Deleaker on Windows. An added bonus is Deleaker does not hold up the application operation like Valgrind does. For any Windows developer, Deleaker is an indispensable and time-saver tool to track down memory leaks and saves invaluable developer time to focus on doing the value-added work that brings in the dough. Highly recommended to any developer making a livelihood writing code on Windows!

Financial Incentive Disclaimer: It should be disclosed that no monetary gain changed hands in writing this review except a copy of Deleaker that is essential for doing the review.

Visual C++ 6.0 Developer’s Reference

VisualCppDocs

Came across this picture of Visual C++ 6.0 Developer’s Reference(1998) posted by raddevus.

I had a C++ Master Reference published in 1999. It has 1500 pages of C++ language and library reference! I had perhaps only read one page(about atoi()). It is like a predecessor of Cppreference except it is printed on book and is written by one author, Clayton Walnum.

cpp_master_ref

inside_cpp_master_ref

Running VC++ Executable on User Machine Without its DLLs

Since this question is asked on CodeProject today, I’ll answer it here.

To deploy without having to install the Visual C++ DLLs, the program has to be linked statically.

Linking to C runtime statically: Right-click on your project in the Solution Explorer and select Properties and go to C/C++ -> Code Generation. Select Multithreaded (/MT) for Release build or Multithreaded (/MTd) for Debug build.

static_c_runtime_libs

Where are the single-threaded options? Microsoft removed them as most programs are multithreaded these days.

If your program is using MFC, do this to link to MFC runtime statically: Right-click on your project in the Solution Explorer and select Properties and go to Advanced and select Use MFC in a static library under Use of MFC.

mfc_static_lib

The downside to linking statically is your executable size will be bigger but it only links the classes and functions your executable calls whereas, in the dynamical linkage case, the VC++ DLLs have to contains all the code regardless your executable calls them or not. If you package the VC++ DLLs in your installer, very likely your user has to download a larger package than one statically linked executable.

Note: C++/CLI, C++/CX and C++/Winrt programs cannot be linked statically to the C runtime. If your program links to DLLs written in the previously mentioned C++ languages, Visual C++ would not allow your program to link statically to the C runtime or MFC runtime.

When linking dynamically, then download VC++ redistributable to install on your client machine before running your program.

 

Floating-Point Article Win January Prize

My floating-point article won the best article prize for the articles posted in month of January 2020. The prize is a priceless CodeProject mug(above picture) which is just delivered to my house. The impetus to writing this article started with a rule enshrined in the company wiki that “all multiplications must be converted to divisions because division is more accurate”, to paraphrase the software architect. This was not the only floating-point misconception I encountered over the years. In order to prepare myself to write this article, I read many resources. One book published in 2000, stated floating-point multiplication is faster than integer multiplication, is no longer true as integer multiplication performance has caught up and this has to be taken out of the article. Prior to my article, there are existing floating-point articles on CodeProject but they all suffered the same problem of assuming the reader to know substantial amount of floating-point format details without explaining the fundamental. Least to say, not many readers understand their articles. I know you are dying to read my prize-winning article now, here it is:

Succinct Guide to Floating Point Format For C++ and C# Programmers.

I hope you enjoy reading it as much as I enjoyed writing it!