A crash in QFontMetrics::boundingRect()
Hello everyone,
We are using Qt 4.7.3 on Embedded Linux on PowerQuicc II MPC8347E.
We have implementation of Label class that is derived from QLabel class. The method setText is overridden and it searches for maximal applicable font size to fit the whole text in the label space. After it finds the font size, it sets the font size and text to label.
Sometimes our application crashes with the following stack trace:
SIGSEGV handler - signal: 11
SIGSEGV handler - obtained 20 frame(s)
Frame 0 : "/dvs/bin/GApplication() [0x100074c4]"
Frame 1 : "[0x100344]"
Frame 2 : "/opt/Qt/lib/libQtGui.so.4(_ZN14QFontEngineQPFC2ERK8QFontDefiP1 1QFontEngine+0x514) [0xecca04c]"
Frame 3 : "/opt/Qt/lib/libQtGui.so.4(+0x3cb8d0) [0xebfe8d0]"
Frame 4 : "/opt/Qt/lib/libQtGui.so.4(_ZN13QFontDatabase8findFontEiPK12QFo ntPrivateRK8QFontDef+0x3b4) [0xec04724]"
Frame 5 : "/opt/Qt/lib/libQtGui.so.4(+0x4989c8) [0xeccb9c8]"
Frame 6 : "/opt/Qt/lib/libQtGui.so.4(+0x3b2e4c) [0xebe5e4c]"
Frame 7 : "/opt/Qt/lib/libQtGui.so.4(_ZNK11QTextEngine21shapeTextWithHarf buzzEi+0x388) [0xec1be08]"
Frame 8 : "/opt/Qt/lib/libQtGui.so.4(_ZNK11QTextEngine9shapeTextEi+0xf8) [0xec1c948]"
Frame 9 : "/opt/Qt/lib/libQtGui.so.4(_ZNK11QTextEngine5shapeEi+0xc8) [0xec1cd4c]"
Frame 10 : "/opt/Qt/lib/libQtGui.so.4(_ZN9QTextLine13layout_helperEi+0x131 0) [0xec281f0]"
Frame 11 : "/opt/Qt/lib/libQtGui.so.4(_ZN9QTextLine12setLineWidthEd+0xf4) [0xec28f2c]"
Frame 12 : "/opt/Qt/lib/libQtGui.so.4(+0x2e1df0) [0xeb14df0]"
Frame 13 : "/opt/Qt/lib/libQtGui.so.4(+0x2e27a0) [0xeb157a0]"
Frame 14 : "/opt/Qt/lib/libQtGui.so.4(_ZNK12QFontMetrics12boundingRectERK5 QRectiRK7QStringiPi+0x14c) [0xebf7310]"
Frame 15 : "/dvs/bin/libUserInterface.so.1(_ZN5Label7setTextERK7QString +0x630) [0xf7a4d80]"
Frame 16 : "/dvs/bin/libUserInterface.so.1(_ZN13DialogBuilder8addLabelE NS_7LabelTpERK7QStringP10QBoxLayout+0x53c) [0xf7ef848]"
Frame 17 : "/dvs/bin/libUserInterface.so.1(_ZN13DialogBuilder7setupUIER K14WidgetGeometryRK16DialogDescriptor+0x584) [0xf7f28f0]"
Frame 18 : "/dvs/bin/libUserInterface.so.1(_ZN12CommonDialog7setupUIERK 14WidgetGeometryRK16DialogDescriptor+0x28) [0xf7f34a4]"
Frame 19 : "/dvs/bin/libUserInterface.so.1(_ZN10DialogView14initializeV iewERK16DialogDescriptor+0x12c) [0xf80bff0]"
Here are some facts regarding the error:
- The error is hard to reproduce. Sometimes we need 5 minutes and sometimes we need an hour to trigger the error.
- The error is triggered by button pressed, when the text in the label is changed (our code searches for maximal applicable font size to fit whole text in the label space)
- The error is probably triggered when text contains UTF8 characters that are not from Latin1 charset (for example Chinese characters)
- Our assumption is that QFontMetrics::boundingRect was called with the same values for arguments before the crash, because we always have the same text on the screen and only the language can be changed
Implementation of our Label::setText method:
Code:
void Label::setText(const QString& newText)
{
// Get label font
QFont labelFont
= font
();
// Check is font pixel size is initialized, if not initialize it
if (myFontPixelSize <= 0)
{
myFontPixelSize = labelFont.pixelSize();
}
// Get text for testing, remove italic flags and replace line breaks with a new line
testText.
replace(QRegExp("<i[^>]*>", Qt
::CaseInsensitive),
"");
testText.
replace(QRegExp("</i[^>]*>", Qt
::CaseInsensitive),
"");
testText.
replace(QRegExp("<br[^>]*>", Qt
::CaseInsensitive),
"\n");
// Get saved font size
int fontPixelSize = myFontPixelSize;
// If font size if larger than zero, proceed
if (fontPixelSize > 0)
{
// Initialize the 'fit' flag to false
bool fit = false;
// Set test pixel size
labelFont.setPixelSize(fontPixelSize);
// Get alignement flags
int flags = alignment();
// If we support word wrap, add it
if (wordWrap() == true)
{
flags |= Qt::TextWordWrap;
}
// Test until we can fit with regular font pixel size
while (fit == false && fontPixelSize > 0)
{
// Set pixel size
labelFont.setPixelSize(fontPixelSize);
// Font metrics
// Get bounding rect, we need to take into account 2 vertical and 2 horizontal margins
QRect bound
= fm.
boundingRect(0,
0, contentsRect
().
width() - 2 * margin
(),
contentsRect().height() - 2 * margin(), flags, testText);
// Check bounding rect width and height, we need to take into account 2 vertical and 2 horizontal margins
if ((bound.width() <= contentsRect().width() - 2 * margin()) &&
(bound.height() <= contentsRect().height() - 2 * margin()))
{
// We can now fit
fit = true;
}
else
{
// Decrease font pixel size
fontPixelSize--;
}
}
// Set last font
setFont(labelFont);
}
// Set new text
}
Any advice or further direction will be appreciated.
Thanks,
Nebojsa
Re: A crash in QFontMetrics::boundingRect()
We discovered what the problem was. Qt uses temporary folder /tmp/qtembedded-0/fonts for writing .qsf files. On our unit temporary folder is on RAM disk and it was 4MB. The usage of different sized Chinese letters produce large .qsf files and at one moment our RAM disk becomes full and the application crashes.
To resolve that problem we increased the RAM disk size to 128 MB and we reduce the possible number of different font sizes for Chinese letters.
Is it possible to clear .qsf files from /tmp/qtembedded-0/fonts while the application is running?
Thanks,
Nebojsa