Qt Commercial Support Weekly #3 – Handling Subtle Problems

In support,  I see all kinds of different questions come up, we get the easy ones from time to time which are still nice to answer because it means that we are able to help someone quickly, which is good for the person asking the question.  Even though sometimes the question might be out of scope for Qt Commercial Support, we do try to give an answer as best as we can be it a C++ question or a question on which third party library is best to use to provide certain functionality.  These cases do give a sense of satisfaction back to me, at least, as well as I know that I have managed to help.

On the opposite side of the scale, we do have the detailed, involved problems that can take a bit of going back and forth trying to understand the issue and then doing some digging in to try and understand what is going wrong and how to solve it.  It isn't always the case that Qt is the problem, although on appearances it can be that is the case, there are times when there is a subtle problem deep down in the user's code that is actually the cause of the problem.

 

One major cause of these sort of problems is actually on Windows, as it allows you to specify a runtime library to be used for the application. This can be either -MD(d) or -MT(d); the former being for the multithreaded C runtime library as a dll and the latter being the multithread C runtime library as a static library.  Qt always uses -MD(d) as the option for building and therefore any third party libraries and your application has to use the exact same option as well, otherwise it will run into problems later on when running the application.  These problems may not be noticed straight away, but in a memory intensive application you can run into memory corruption and crashes that seemingly don't make any sense when you look at the call stack.

 

If you are using qmake and you don't link to any third party libraries (other than Qt) and you have no idea what I am talking about, then you have nothing to worry about.  However, if you are using third party libraries or you have the feeling that you may have changed the settings to be -MT, then you can do the following check to see if you are potentially going to have a problem.  By rebuilding the application you can see if you have any linker warnings that are referring to default libraries. If you do (or you have specified /NODEFAULTLIB in some form), then this is an indication of a problem.  If you see this warning, then check that all of your libraries and application is using the same setting (either -MD or -MDd). If any of them are not right, then change it and build that element again and then the application.  Doing this check will save you a lot of headaches later on when you see a strange crash that has you scratching your head.

 

There are, of course, other subtle problems that you may run into not just on Windows. One example that came through recently is involving gradients.  However, how these get used can be quite subtle, because it may work in a certain situation such as a QTabWidget where you can see that the gradient has been painted across the whole tab widget, but if a small part of it, such as a tab is repainted with the same gradient, then it gets repainted incorrectly, appearing to be painting the gradient separately in that area.

The reason this was a problem was due to the coordinate mode.  In QGradient that can be used - QGradient::LogicalMode, QGradient::StretchToDeviceMode and QGradient::ObjectBoundingMode.  The default is LogicalMode which uses the specified points for the gradient and just goes from one to the other ignoring any device rectangles and so on.  In the case that I had handled the gradient was set to be QGradient::StretchToDeviceMode, which uses the coordinates for the device being painted.  When this was set on the QTabWidget then it would appear to be working just fine because the painter would be painting on the whole of the QTabWidget and therefore the gradient was rendered as expected.  However, when it was painting the tab that was selected when it got clicked on then it would then end up using the area that was specifically marked for updating and therefore rendered the whole gradient compressed into that small area.  Therefore, the solution was to use ObjectBoundingMode instead as that would ensure that the widget rectangle would be used for the gradient area, irrespective as to what part of it was actually being updated.

 

It sounds easy now, but it certainly took some investigation to track down that problem as it is not necessarily the first thing that comes to mind when you see a redraw problem, I am glad to say I came out the wiser for having dealt with that issue.

 

Before I close for the week, I would like to make a request.  When you submit cases to us, it doesn't hurt to let us know what you configured Qt with even if the issue is not a build one. We try to get all the information we need in the drop-downs on the case form but we can't overdo it with that otherwise it gets a bit much.  Knowing the configuration can make the difference between us reproducing it the first time as opposed to having to ask for more information.  Especially on Mac where the SDK specified, or whether it is carbon or cocoa, can make a lot of difference.


Blog Topics:

Comments