Category Archives: C++

Handling errors at compile time in C++

We had a discussion with colleagues on why in the following code we cannot simply use

static_assert(false)

but need to do a trick with ‘always_false’:

#include <type_traits>

template<typename>
struct always_false : std::false_type {};

template<typename Type>
constexpr int Get()
{
    if constexpr (std::is_same_v<Type, int>)
    {
        return 1;
    }
    else if constexpr (std::is_same_v<Type, bool>)
    {
        return 2;
    }
    else {
        static_assert(always_false<Type>::value);
    }
}
(more…)

Exponential growth policy of std::vector

Once std::vector is filled (size() equals to capacity()), a subsequent push_back(…) results in an exponential expansion of the vector capacity. The following table shows that the expansion happens when the index reaches a power of two:

index: 0, capacity: 1, address: 0x1fa6c20
index: 1, capacity: 2, address: 0x1fa6c40
index: 2, capacity: 4, address: 0x1fa6c20
index: 4, capacity: 8, address: 0x1fa6c60
index: 8, capacity: 16, address: 0x1fa6c90
index: 16, capacity: 32, address: 0x1fa6ce0
index: 32, capacity: 64, address: 0x1fa6d70
index: 64, capacity: 128, address: 0x1fa6e80
index: 128, capacity: 256, address: 0x1fa7090
index: 256, capacity: 512, address: 0x1fa74a0
index: 512, capacity: 1024, address: 0x1fa7cb0
index: 1024, capacity: 2048, address: 0x1fa8cc0
index: 2048, capacity: 4096, address: 0x1faacd0
index: 4096, capacity: 8192, address: 0x1faece0
index: 8192, capacity: 16384, address: 0x1fb6cf0
index: 16384, capacity: 32768, address: 0x1fc6d00
index: 32768, capacity: 65536, address: 0x1fe6d10
index: 65536, capacity: 131072, address: 0x2026d20
index: 131072, capacity: 262144, address: 0x20a6d30
index: 262144, capacity: 524288, address: 0x21a6d40
index: 524288, capacity: 1048576, address: 0x23a6d50
index: 1048576, capacity: 2097152, address: 0x27a6d60
index: 2097152, capacity: 4194304, address: 0x2fa6d70
index: 4194304, capacity: 8388608, address: 0x7f8e9225f010
index: 8388608, capacity: 16777216, address: 0x7f8e8e25e010
index: 16777216, capacity: 33554432, address: 0x7f8e8625d010
index: 33554432, capacity: 67108864, address: 0x7f8e7625c010
index: 67108864, capacity: 134217728, address: 0x7f8e5625b010
index: 134217728, capacity: 268435456, address: 0x7f8e1625a010
index: 268435456, capacity: 536870912, address: 0x7f8d96259010
index: 536870912, capacity: 1073741824, address: 0x7f8c96258010

(more…)

How to erase an element with a reverse iterator from C++ container

The following C++ code demonstrates how to erase an element a reverse iterator points to:

#include <iostream>
#include <set>
#include <cassert>

int main()
{
    std::set<int> set;
 
    set.insert(15);
 
    std::cout << set.size() << " ";
 
    auto ri = set.rbegin();
 
    auto i1 = --ri.base();
 
    auto i2 = --set.end();
 
    assert(i1 == i2);
 
    set.erase(i1);
 
    std::cout << set.size() << std::endl;
}

The output is ‘1 0’. The key point here is that the reverse iterator is an adaptor for reverse-order traversal that can be created from forward iterator with std::make_reverse_iterator.

An example of how GCC thread sanitizer works.

The following simple code C++ example can be used for investigation of how GCC thread sanitizer works:

#include <mutex>
#include <atomic>
#include <iostream>
#include <thread>

std::mutex mutex;
int a = 3;
const size_t size = 1000 * 1000;
std::atomic<int> b(1);

void testA()
{
	for (size_t counter = 0; counter < size; counter++)
	{
		++b;
		std::unique_lock<std::mutex> lock(mutex);
		++a;
	}
}

void testB()
{
	for (size_t counter = 0; counter < size; counter++)
	{
		--b;
		std::unique_lock<std::mutex> lock(mutex);
		--a;
	}
}

int main()
{
	std::thread t1(testA);
	std::thread t2(testB);
	t1.join();
	t2.join();
}

(more…)

Multiple views with OsgQtQuick

I wrote a sample application using OsgQtQuick that shows the Earth in two views:

with the following QML, that I copied from OsgQtQuick samples:

(more…)

A sample C++ code demonstrating why int is not atomic

The code below demonstrates why it is not guaranteed that 4-byte value being written by another thread is read either as original or final, but it can be read “partially written”:

static constexpr int offset=2;
alignas(64) char vars[64+4-offset];
static volatile unsigned * const p = reinterpret_cast<unsigned *>(&vars[64-offset]);

unsigned getVar()
{
    return *p;
}

void loop()
{
    while(true)
    {
        *p = -1;
        *p = 0;
    }
}

#include <thread>
#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <map>

int main()
{
    std::thread thread(loop);
    std::map<unsigned,int> xs;
    for(int i=0;i<10000000;++i)
    {
        const auto x=getVar();
        ++xs[x];
    }
    for(const auto& x : xs)
        std::cout << std::setfill('0') << std::setw(8) << std::hex << x.first << ": " << std::dec << x.second << " times\n";
    std::exit(0); // exit, killing the thread without abnormal termination via std::terminate
}

(more…)

Numeric promotions and conversions in C++

In the following C++ code the values of ‘z’ and ‘n’ are undefined, because they are the result of an operation with signed integer arithmetic overflow (‘x’ and ‘y’ are first implicitly converted to signed int). The value of ‘w’ is implementation defined, because it is the result of a conversion:

#include <iostream>
#include <bitset>

int main(int argc, char *argv[])
{
    unsigned short x = 65535, y = x;
    unsigned short z = x * y;
    unsigned int n = x * y;
    std::cerr << "z = " << std::bitset<16>(z) << ", n = " << std::bitset<32>(n) << ", sizeof(int) = " << sizeof(int) << std::endl;

    short w = 0x80000000;
    
    return 0;
}

see Numeric conversions section of Implicit conversions article.

Comparison of std::mutex and std::atomic performance

The following C++ code compares the performance of std::atomic and std::mutex:

#include <atomic>
#include <mutex>
#include <iostream>
#include <chrono>
#include <thread>

const size_t size = 100000000;
std::mutex mutex;
bool var = false;

typedef std::chrono::high_resolution_clock Clock;

void testA()
{
    std::atomic<bool> sync(true);
    const auto start_time = Clock::now();
    for (size_t counter = 0; counter < size; counter++)
    {
        var = sync.load();
        //sync.store(true);
        //sync.exchange(true);
    }
    const auto end_time = Clock::now();
    std::cout << 1e-6*std::chrono::duration_cast<std::chrono::microseconds>(end_time - start_time).count() << " s\n";
}

(more…)

Detecting memory leaks of C++ application in Ubuntu

First, I tried Valgrind tool using the following command:

valgrind --tool=memcheck --leak-check=yes ./app

With some large QT application started for some short period I got the following output:

==7090== HEAP SUMMARY:
==7090==     in use at exit: 5,623,365 bytes in 36,268 blocks
==7090==   total heap usage: 32,454,680 allocs, 32,418,412 frees, 12,822,939,874 bytes allocated
................................
==7090== LEAK SUMMARY:
==7090== definitely lost: 20,163 bytes in 74 blocks
==7090== indirectly lost: 60,053 bytes in 1,273 blocks
==7090== possibly lost: 396,167 bytes in 2,169 blocks
==7090== still reachable: 4,834,822 bytes in 31,576 blocks
==7090== suppressed: 0 bytes in 0 blocks
==7090== Reachable blocks (those to which a pointer was found) are not shown.
==7090== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==7090==
==7090== For counts of detected and suppressed errors, rerun with: -v
==7090== Use --track-origins=yes to see where uninitialised values come from
==7090== ERROR SUMMARY: 20905 errors from 1583 contexts (suppressed: 15 from 2)

When I left this app running for the night (approximately 16 hours), I got the following summary:

==3816== HEAP SUMMARY:
==3816==     in use at exit: 7,746,701 bytes in 36,248 blocks
==3816==   total heap usage: 827,800,342 allocs, 827,764,094 frees, 105,404,761,516 bytes allocated
..................................
==3816== LEAK SUMMARY:
==3816== definitely lost: 19,835 bytes in 38 blocks
==3816== indirectly lost: 59,805 bytes in 1,237 blocks
==3816== possibly lost: 396,167 bytes in 2,169 blocks
==3816== still reachable: 6,958,734 bytes in 31,628 blocks
==3816== suppressed: 0 bytes in 0 blocks
==3816== Reachable blocks (those to which a pointer was found) are not shown.
==3816== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==3816==
==3816== For counts of detected and suppressed errors, rerun with: -v
==3816== Use --track-origins=yes to see where uninitialised values come from
==3816== ERROR SUMMARY: 13022 errors from 1574 contexts (suppressed: 10 from 2)

It means that the app leaks about 0.126 MB/hour ( (6958734 – 4834822) / 16 / 1024.0 / 1024.0) and totally for the night 2.02 MB, and probably it is not a leak, because the app has pointers to the allocated memory (it is reachable), but it does not clean exit.

To figure out how it works I built the following trivial program:

int main()
{
  int *a = new int[100];
}

with debug information and started the tool:

g++ -g -o ex ex.cpp
valgrind --tool=memcheck --leak-check=yes ./ex

In the output the tool shows line number 3 where memory leak is occurred:

==22042== Memcheck, a memory error detector
==22042== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==22042== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==22042== Command: ./ex
==22042==
==22042==
==22042== HEAP SUMMARY:
==22042==     in use at exit: 73,104 bytes in 2 blocks
==22042==   total heap usage: 2 allocs, 0 frees, 73,104 bytes allocated
==22042==
==22042== 400 bytes in 1 blocks are definitely lost in loss record 1 of 2
==22042==    at 0x4C2B800: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==22042==    by 0x40061B: main (ex.cpp:3)
==22042==
==22042== LEAK SUMMARY:
==22042==    definitely lost: 400 bytes in 1 blocks
==22042==    indirectly lost: 0 bytes in 0 blocks
==22042==      possibly lost: 0 bytes in 0 blocks
==22042==    still reachable: 72,704 bytes in 1 blocks
==22042==         suppressed: 0 bytes in 0 blocks
==22042== Reachable blocks (those to which a pointer was found) are not shown.
==22042== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==22042==
==22042== For counts of detected and suppressed errors, rerun with: -v
==22042== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

Links:

  1. How I can detect memory leaks of C++ application in Linux (Ubuntu OS)?
  2. How to check for memory leaks in a large scale c++ Linux application?
  3. Still Reachable Leak detected by Valgrind
  4. With Memcheck’s memory leak detector, what’s the difference between “definitely lost”, “indirectly lost”, “possibly lost”, “still reachable”, and “suppressed”?
  5. Valgrind: can possibly lost be treated as definitely lost?

Another alternative is calling mallinfo() function in C++ code. The following code gets something like total heap size of the process:

int usedmem = mallinfo().uordblks;

Using this function I wrote a QT widget that shows memory usage in application status bar:

#include <QLabel>
#include <malloc.h>

class MemoryStatusWidget : public QLabel
{
public:
    MemoryStatusWidget(QWidget *parent = nullptr);

public:
    void timerEvent(QTimerEvent *) override;
};

MemoryStatusWidget::MemoryStatusWidget(QWidget* parent)
    : QLabel(parent)

{
    startTimer(1000);
}

void MemoryStatusWidget::timerEvent(QTimerEvent *)
{
    int usedmem = mallinfo().uordblks;

    setText(tr("Memory Usage:%1 MB").arg(QString::number((double)usedmem / (1024 * 1024), 'f', 3)));
}

Detecting leaks on Windows

Just in case if you need to detect leaks on Windows (where Valgrind doesn’t work and will never work by design), give Deleaker a try. By the way it can be integrated with Qt Creator, see video on YouTube.

Lines 3D application structure (Windows Store version)

Lines 3D game is a UWP application based on “XAML App for OpenGL ES (Universal Windows)VS2015 project template (written in C++/VS2015 using OpenGL ES 2.0 and elements of OpenGL 3.0). You can install Lines 3D  from Windows Store and play for free, or at least see the game screenshots.

Main components

Game logic and OpenGL rendering engine in Lines 3D are cross-platform. Their code uses STL, OpenGL and abstract C++ interfaces for doing the following tasks:

  • Loading sounds from wav files and playing them with different speed and volume.
  • Loading textures from PNG images (this code uses Windows API, but probably it can be made cross-platform).
  • Logging game events, such as “game over” to the Windows Store. They used to collect statistics on what game levels the users play and what score they get. The possible application crashes (unhandled exceptions and memory failures) and internal errors (like file not found, etc.) are also logged to the Windows Store.
  • Accessing application installation path and application data path in the file system.

All the graphic controls, including the main windows, application bar (main menu), dialogs, message boxes and advertising are written using XAML and Windows-specific code.

(more…)