background

Simple bugs that crashed my mind

This post is more about a memorial of my errors or those I found during the years than a tutorial or research entry. Even though, I'll try to give an explanation about why it happened and what we try to take into account for the future. They're usually simple errors but hard to find when you don't know what you're looking for. Some times it crashes but other times it just causes unexpected behavior.

I've some for C++ and other about Qt. I think it's quite interesting to see both of them because their types and reasons are quite different. While in C++ we have full control about memory allocation and deallocation in Qt we have the re-parenting issue.

Simple bugs in C++

Old C-style arrays are deprecated

The other day I was having some random crash with what look like a corrupted stack, but everything was fine. I had fill an array of doubles in a loop and it was coded in old C-style:

Despite the fact of having the number 12 hard coded, don't you see anything weird? Yes, the parentheses! Array is in fact a pointer to a double with value 12 and then we were iterating over the unknown. Why we don't use the std::array type? It'd be easy, nice and clean:

As you can see: easy, clean and without any problem!

When you mix up pointer to an object with references of an object

This has happened several times because it's not intuitive what we want to achieve. The code compiles and runs properly, almost. I've a structure as a singleton where I take one object, update or modify it and then I commit the changes to the database. I'll show just the part of the code necessary:

First of all, we'll get close to the functionality of the commit method. There we get a clip, modify it and the commit. The clip is modified, and commit properly to the database. The problem is that I was doing a copy of that clip, I was not modifying the clip IN the DataStructure. The solution was easy:

The problem now is: what happens if id is not found? We return a reference of a temporary object, so when we go out of the post method scope it is dereferenced and removed. So our pointer is not valid anymore. Obviuosly if we want the modification and commit behavior we have two options: do it inside the DataStructure or return a pointer or nullptr instead:

Solved!

A variant of the previous one

In the code above I said I have a method postPtr (int id) that returns a pointer to a Post of the inner map. The reason I have it is to allow other programmers to access that structure and modify the data. If a user wants a specific Post but doesn't want to modify it, I have another method called getPost (int id) const that returns a const reference to a copy of the object with that id and if it's not found it returns a new object so the user can check if is valid.

I say so because today I found a crash in the application because it was supposed to user getPost () instead of the pointer return. Every call inside that particular method was only to get information from the Post instead of modifying the data. In that method it should be used the constant method. But instead, it was used the pointer without checking if it was nullptr.

In addition, the method had two calls to a get method that in addition to return the value it applies an internal operation that modifies it. So:

  1. The reason was crashing is because the method called changed from getPost to post. From const reference of an object to a pointer to an object (or nullptr!)
  2. The reason of that change is because we need to make some modifications in that Post object in that method but the change log only shown that get methods where called.
  3. One get method wasn't a const method as its name indicate. It was doing more than the name of the method

So remember: the name of the method must explain what the method does and the method only must do one thing at a time. If it's a get method it must be const always.

Simple bugs in Qt

Easy to create, easy to copy

One of the main problems of Qt is that we are use to really on copy-on-write (COW) optimization and therefore we assume that we can write atrocities like the following:

I really don't know from where I start, I just so wrong in all ways that the best way is just to remove everything and start from scratch. The variable <em>mSet</em> is a field of the class, as you can see by the allocation is a pointer to a QSet of integers.So, let's start with the first line or better say for the absence of a previous one:

We just had the first line and we cause the first memory leak. After that we call the static method fromVector with a temporary object that is destroyed after using it. The same happens with the temporary object from that method when we pass the parameter to the fromList. So, in a single line we have 3 expensive object creations (temporary QVector, temporary QList and temporary QSet). In this particular case we cannot use std::move since the parameter the static methods are waiting for is a const reference. In the following line we take that temporary object and pass it as a constructor parameter to create a new QSet and it performs a deep-copy. Wonderful!

Please, take into account that most of the times is easy to add a single loop than several calls to static methods chained:

The loop of the death

This particular bug has happened to me several times and the reason is simple: too fast writing code. Remember to double check your call al the time! In the following code I had to process an event, do some operations and then pass to the base class so it can continue its flow:

It was solved before was committed but is so embarrassing I wanted to have it here.

Signals with params between threads

In Qt as well in other frameworks or libraries we have signals that allows us to send parameters using some sort of callback system (we'll see the inner implementation in further post). It means that we can also use it to send information between threads. But we always must remember what are we sending. In the following code I've avoided all the noise of the macros and declarations so we can focus on the signal's parameter:

This is a potential failure. If we are sending constant references to an object between threads is possible that when the signal is processed, the data is no longer valid. We always must send copies of an object or if we want to share data, a shared pointer:

And that's all... for the moment!


background

CustomWindow in Qt (create your own QWindow)

Brief introduction

I've seen several questions in the Qt Forum about how to customize or create our CustomWindow predefined window title buttons or the styles of it. First of all is necessary to explain that this is not a trivial issue since the OS API defines these controls and styles.

In the case of Windows, the title bar is created by Windows Manager so it is impossible to modify it. If we want a personalized title bar or modify the styles of the border of the window or whatever, it is necessary to remove it and then, create our custom QWidget with our own title bar. Before we start to write our own custom QWindow we need to understand that is not an easy task. Our QWidget must fulfill the following requirements:

  • Catch some mouse events: press, release, move… In order to know where to move or how to resize the window.
  • Implement the top-right buttons behavior: close, minimize, maximize, restore…
  • Manage the include of the central widget that will has the main functionality.
  • We could want to add a top-left menu and the title of the window. It is necessary to implement too.
  • The good things that provide us a custom title bar is the possibility to add new buttons with extended functionality, customize the top-left menu with our own options and definitely, to have our application window style unified.

The best way to learn Qt goes trough code, code & code. In this case, create our custom window title and all the functionality it involves is a good way to learn the Qt window management.

My custom QWindow

I've crafted my own CustomWindow with a customized title bar. It has a minimalist aspect and you can modify it as much as you want. If you just want it raw, take it as it is!

The class has a method to set the central widget (that it also sets the title of the window) and another to set the menu of the top-left button. One important question is whether we want to connect the signals of the top-left menu with slots or other signals of our CentralWidget.

A connect links two objects by their memory addresses, so is not important where we define the connect but it is which objects we want to link. In conclusion, we can connect the signals of the actions of our menu with the slots of our central widget outside the CustomWindow and then set the menu and the central widget to it without problems.

The code is composed only by the class CustomWindow and you can find a link to the code at the end of the post. Following I explain briefly how to use it (although I've commented the code).

Step by step

  1. Create an instance of our CentralWidget (named i.e. centralWidget).
  2. Create a QMenu with QActions or get one created (named i.e. titlebarMenu).
  3. We create an instance of the class CustomWindow.
  4. Connect the signals of the QMenu to the slots of the CentralWidget (or to other places).
  5. We use CustomWindow::setCentralWidget(centralWidget, “Our applications”); to set the central widget
  6. We use CustomWindow::setTitlebarMenu(titlebarMenu, “path/to/menu/img.png”); to set the menu and an icon to it. The menu icon is optional.
  7. We use CustomWindow::setTitlebarMode(CustomWindow::TitleMode); with the option of TitleMode that we want. The title mode defines which buttons and behavior we want to have in the window. It allows us to create dialogs, windows or other window types without any effort.
  8. IMPORTANT: If we have a close button or a close action in our centralWidget, it is necessary to connect it to the CustomWindow instance to close it. There are two ways to do it:
    1. Connecting the signal of the centralWidget to CustomWindow::close().
    2. Emit a signal MyWidget::cancelled() from our centralWidget since it is already connected inside CustomWindow to close() slot.
  9. Call CustomWindow::show(); and enjoy!

Note: If we skip the 8th step, when we click the close/cancel button, only the central widget will closed.

You can find the CustomWindow code in my GitHub repository.


background

Logging with Qt

Logging with Qt

Logging messages is an important part of our app and sometimes we can't find the right way to do so. It depends on how we want to work with that but of course that Qt provide us with some nice options.

Redirect QDebug to a file

Some times we prefer to analyse the our application debug messages in a separated file. It is useful when we want to work with Qt-Creator in full code window and we have two monitors (one for coding and another for application execution and debug file). To redirect the output we have to type in Qt:

Then, in main function we have to add the following line:

qInstallMessageHandler(customMessageHandler);

Redirect QDebug in our custom class

If we want to redirect the output of our custom class to QDebug, it is necessary to declare the operator << of QDebug type as a friend method:

friend QDebug operator << (QDebug d, const Protocol &p);

Have you own logger

Time ago I created a simple logger, nothing fancy, but easy to integrate. It's a single class that manages several files depending the module and the log level. It makes easier to integrate in your code since there is no dependencies, linking or anything else you need to take into account.

Initially it's planned to be organized by modules, so for each "part" of your code that you want to log it can only be a file. It gives you the possibility to structure your code in different layers and log them. For now, all log messages of a module are printed in the same file, whatever their log level is.

The way to work with this logger is really easy:

The next task I have is to make possible to create files by log level instead of by module. For me it looks a bit messy since you may lose the code traceability, but it's easier to show errors or warnings.