Skip to content

QML Engine Deletes C++ Objects Still In Use – Revisited with Address Sanitizers

Two years ago, I spent three days to figure out why the driver terminal of a sugar beet harvester crashed (see my original post). The crash happened after going through the same six-step interaction at least four times. The reason was that the C++ code accessed an object that the QML engine had already deleted. For the last two years, I have heard a lot of good things about address sanitizers. When I threw address sanitizers at the old problem, they identified the problem right away. Recently, address sanitizers helped me to locate and fix some strange crashes on a legacy application. Sanitizers will be part of my debugging toolbox from now on.

Read More »QML Engine Deletes C++ Objects Still In Use – Revisited with Address Sanitizers

Introduction to the SAE J1939 Standard

In the early days of controller area networks (CAN), every device manufacturer interpreted CAN frames in its own proprietary way. When you changed the engine of a harvester from Volvo to MAN, you would have to reimplement the communication with the engine from scratch. Fendt tractors wouldn’t be able to communicate with John Deere implements and vice versa. The J1939 standard brought order into this Babylonian chaos and reduced the development efforts significantly.

Read More »Introduction to the SAE J1939 Standard

Safe-Guarding the (L)GPL Future of Qt

The little known KDE Free Qt Foundation makes sure that Qt stays free and open-source. It guarantees that all Qt modules currently licensed under LGPLv3 must continue to be available under LGPLv3 in the future. This covers all modules from Qt Essentials and many add-on modules. If The Qt Company discontinued the FOSS version of Qt, the Foundation would have the right to make Qt available under the BSD license. This is a very powerful protection of free and open-source Qt.

Read More »Safe-Guarding the (L)GPL Future of Qt

Detecting Overdraw in QML HMIs with GammaRay

Overdraw happens when one QML item fully eclipses another QML item. The QML renderer always draws both items, although there is no need to draw the eclipsed item. You must help out the renderer by explicitly setting visible: false on the eclipsed item.

On embedded systems, heavy overdraw makes animations or flicking jerky. In the worst case, it freezes your HMI. Fortunately, the Qt experts at KDAB developed a tool, GammaRay, which makes detecting overdraw a piece of cake. I’ll show you how to build GammaRay, how to detect overdraw in the home screen of a harvester HMI, and how to fix the overdraw.

Read More »Detecting Overdraw in QML HMIs with GammaRay

Comparing Two Floating-Point Numbers

The mathematician Leopold Kronecker is believed to have said:

God made the integers, all else is the work of man.

And Kronecker didn’t even know the floating-point numbers “made” for computers. Comparing two numbers of type float or double in C++ and related languages is a source for regular errors. When are the if-conditions in the following code snippet true?

float actual = calculate(10.0f, 0.2f, 45); // 10 - 0.2 * 45 = 1
if (actual == 1.0f) {
    // is this ever executed?
if (actual - 1.0f == 0.0f) {
    // is this ever executed?

The function calculate produces the result 10 – 0.2 * 45 = 10 – 9 = 1 – at least for human beings. So, both conditions should be true. However, they are both false.

If we turn on the warning -Wfloat-equal, the compiler will warn us that comparing floating point with == or != is unsafe. The compiler tells us what is wrong, but not how to fix it. I’ll explain why the above “solution” is wrong, why another obvious “solution” is nearly as bad, and why even the Qt function qFuzzyCompare can still be improved.

Read More »Comparing Two Floating-Point Numbers

QTest: Data-Driven Unit Tests Are Hard To Understand

Today, I looked at the data-driven unit tests I had written nearly four weeks ago. It took me a couple of minutes to understand the tests again. Understanding my own tests should have been much easier.

Data-driven unit tests in QTest have a fundamental problem. The data goes in one function, say testWriteFrame_data, and the test case working on the data goes in another function, say testWriteFrame. I must go back and forth to understand the test case. While going back and forth, I typically forget one piece of information. So, I must do another round trip.

So, I sat down and converted each row of the table created by testWriteFrame_data into a test function of its own. The resulting test cases are much easier to understand. They have about the same code size as the original solution. But see for yourself.

Read More »QTest: Data-Driven Unit Tests Are Hard To Understand

Deploying Qt Projects to Embedded Devices with CMake

When you run a Qt project, QtCreator first deploys the project to a remote embedded Linux device via ssh and then runs the executable on the remote device. This feature enables nearly instant feedback how your Qt application works on the embedded device.

Deployment works fine with the INSTALLS variable of qmake. It does not work out of the box with the install functions of CMake. Fortunately, the Qt trolls provide a workaround. I’ll explain the workaround with an example CMakeLists.txt file.

Read More »Deploying Qt Projects to Embedded Devices with CMake

QCOMPARE with Custom Qt Types

When you write unit tests, you will have to compare the actual value and the expected value. A simplified example with QStrings would look like this.

void MyTest::testQCompare() {
    auto actualStr = QString{"abba"};
    auto expectedStr = QString{"juhu"};
    QCOMPARE(actualStr, expectedStr);

When you run this unit test, the QTest framework will print the actual value "abba" and the expected value "juhu". This is often enough to know what went wrong.

FAIL!  : MyTest::testQCompare() Compared values are not the same
   Actual   (actualStr)  : "abba"
   Expected (expectedStr): "juhu"

If two values of a custom type differ, the QTest framework will only print the first line: Compared values are not the same. This is not very helpful. How can you make QCOMPARE print the actual and expected for custom types as well?

Read More »QCOMPARE with Custom Qt Types