Category Archives: Programming languages

Why my QT app crashes at the destructor of std::thread on Android 10 devices?

I did some research on why my QT app crashes at the destructor of std::thread on Android 10 devices at the user side with the following call stack:

#00 /apex/com.android.runtime/lib64/bionic/libc.so (abort+160)
#01 /system/lib64/libc++.so (abort_message+232)
#02 /system/lib64/libc++.so (demangling_terminate_handler()+44)
#03 /system/lib64/libc++.so (std::__terminate(void (*)())+12)
#04 /system/lib64/libc++.so (std::terminate()+52)
#05 /system/lib64/libc++.so (std::__1::thread::~thread()+20)
#06 /apex/com.android.runtime/lib64/bionic/libc.so (__cxa_finalize+212)
#07 /apex/com.android.runtime/lib64/bionic/libc.so (exit+24)
#08 /data/app/com.domain.myapp-Rs_sm5VrLR1Jj8QW6oYByA==/lib/arm64/libplugins_platforms_qtforandroid_arm64-v8a.so

and figured out that its likely because std::thread destructor is being invoked while the thread is still joinable at some point of the application execution (thanks to G. M. on stackoverflow.com).

(more…)

C++ binary serialization speed is comparable with std::memmove

Measuring std::memmove speed

I wrote a simple test that outputs std::memmove speed to the console:

AWT_ATTRIBUTE(size_t, element_count, 1000000);

std::unique_ptr<uint8_t> p_src(new uint8_t[element_count]);
std::memset(p_src.get(), 25u, element_count);

std::unique_ptr<uint8_t> p_dst(new uint8_t[element_count]);

context.out << _T("std::memmove: ");

awl::StopWatch w;

std::memmove(p_dst.get(), p_src.get(), element_count);

ReportSpeed(context, w, element_count);

context.out << std::endl;

And the similar tests for std::memset and std::vector::insert.

(more…)

A funny example of C++ code that MS can compile :)

In the code below, static_assert operates on the addresses of local variables, but however MS compiles it and the assertion does not fail:

#include <tuple>
#include <string>
 
struct A
{
    int a;
    double b;
    std::string c;
};
 
void f()
{
    A a{ 1, 3.0, "abc" };
    constexpr auto t1 = std::tie(a.a, a.b, a.c);
    static_assert(&std::get<0>(t1) == &a.a);
}

Use the following command to compile this example:

cl /std:c++17 /EHsc a.cpp
(more…)

Basic ideas of version tolerant serialization in C++

Consider the following scenario: there was structure A in an old version of a C++ application:

struct A
{
    double a;
    int b;
    std::string c;
};

An instance of A was serialized into a file in a binary format and after that the application was updated to a new version.

But in the new version of the application structure A was modified by adding fields d and e and deleting field a:

struct A
{
    int b;
    std::vector<int> d;
    bool e;
    std::string c;
};

and the new version of the application needs to deserialize an instance of its new structure A from the file containing old version of A.

(more…)

A simple C++ serialization framework

I implemented a simple C++ binary serialization framework that makes a structure or class serializable by adding a macro that usually takes one line of code as shown in the example below:

struct A
{
    bool x;
    int y;

    AWL_SERIALIZABLE(x, y)
};

There is also a macro that makes a structure or a class equatable:

AWL_MEMBERWISE_EQUATABLE(A)
(more…)

Parsing GUID in C++ with a regular expression

The code below demonstrates how to parse GUID in C++ using a regular expression:

#include <iostream>
#include <string>
#include <regex>

int main()
{
    static const std::wregex regex(L"[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}");
    
    std::wstring sample = L"850fe1da-0ea6-c1a8-9810-0c1cece30698";

    std::match_results<std::wstring::const_iterator> match;

    if (std::regex_match(sample, match, regex))
    {
        std::wcout << L"matches" << std::endl;
    }
    else
    {
        std::wcout << L"does not match" << std::endl;
    }

    return 0;
}
(more…)

A simple example demonstrating how std::forward works in C++

For example, std::forward comes to play if I implement a template container with two ‘insert‘ function overloads that take the parameters of type const T & and T && respectively. I implement all the private insertion logic with T&&, but when I need to know the original value type passed to ‘insert‘ method I use std::forward as shown in the example below:

#include <iostream>
#include <string>

class Value
{
public:

    Value(const char * sz) : m_s(sz)
    {
    }

    Value(const Value & other) : m_s(other.m_s)
    {
        std::cout << "copy constructor: " << m_s << std::endl;
    }

    Value(Value && other) : m_s(std::move(other.m_s))
    {
        std::cout << "move constructor: " << m_s << std::endl;
    }

    const std::string & ToString() const
    {
        return m_s;
    }

private:

    std::string m_s;
};
(more…)

The string representation of a type is implementation defined in C++

The string representation of a type is implementation defined in C++, for example the following code produce the different output with MSVC, GCC and CLang:

#include <string>
#include <iostream>

struct A {};
class B {};

namespace ns
{
    struct X {};
}

int main()
{
    std::cout << typeid(A).name() << ", " << typeid(B).name() << ", " << typeid(ns::X).name() << ", " << typeid(std::string).name() << std::endl;
    return 0;
}
(more…)

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…)

Conversion of S75 charts to GeoJSON with GDAL org2org utility.

The original S57 map consists of the following layers:

ogrinfo E:\temp\ENC_ROOT\US4CA11M\US4CA11M.000
INFO: Open of `E:\temp\ENC_ROOT\US4CA11M\US4CA11M.000'
      using driver `S57' successful.
1: DSID (None)
2: Point (Point)
3: Line (Line String)
4: Area (Polygon)
5: Meta (None)

So I was able to convert each layer separately one by one without errors:

ogr2ogr -f GeoJSON US1HA02M-Area.json E:\temp\ENC_ROOT\US1HA02M\US1HA02M.000 Area -lco RFC7946=YES -skipfailures
ogr2ogr -f GeoJSON US1HA02M-Point.json E:\temp\ENC_ROOT\US1HA02M\US1HA02M.000 Point -lco RFC7946=YES -skipfailures
ogr2ogr -f GeoJSON US1HA02M-Line.json E:\temp\ENC_ROOT\US1HA02M\US1HA02M.000 Line -lco RFC7946=YES -skipfailures
ogr2ogr -f GeoJSON US1HA02M-DSID.json E:\temp\ENC_ROOT\US1HA02M\US1HA02M.000 DSID -lco RFC7946=YES -skipfailures
Warning 1: No SRS set on layer. Assuming it is long/lat on WGS84 ellipsoid
ogr2ogr -f GeoJSON US1HA02M-Meta.json E:\temp\ENC_ROOT\US1HA02M\US1HA02M.000 Meta -lco RFC7946=YES -skipfailures
Warning 1: No SRS set on layer. Assuming it is long/lat on WGS84 ellipsoid

(more…)