Qt 4.5 drawText crash

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • vdvleon
  • Registratie: Januari 2008
  • Laatst online: 08-06-2023
Hallo iedereen,

Het probleem is als volgt:

Ik heb een script gemaakt die via de opencv library een afbeelding pakt van mijn webcam. Vervolgens converteer ik deze naar een Qt QImage object. Dit gaat allemaal nog zoals het moet. Ook kan ik deze QImage object scalen, mirroren, inverse, etc. Maar zodra ik met een QPainter object tekst probeer toe te voegen aan de QImage object gaat het fout. Zodra ik de painter.drawText functie aan roep krijg ik een Segmenatie fout error.

Toen ik met valgrind ging kijken naar wat er fout ging vond ik dit (tussen de vele foutmeldingen):

Process terminating with default action of signal 11 (SIGSEGV)
==30930== Access not within mapped region at address 0x4
==30930== at 0x4FECA37: QObject::thread() const (qobject.cpp:1283)
==30930== by 0x46A28EA: QFontPrivate::engineForScript(int) const (qfont.cpp:264)
==30930== by 0x46DCCEC: QTextEngine::fontEngine(QScriptItem const&, QFixed*, QFixed*) const (qtextengine.cpp:1747)
==30930== by 0x46DFF79: QTextEngine::shapeTextWithHarfbuzz(int) const (qtextengine.cpp:1112)
==30930== by 0x46E0EE9: QTextEngine::shapeText(int) const (qtextengine.cpp:874)
==30930== by 0x46E1337: QTextEngine::shape(int) const (qtextengine.cpp:1344)
==30930== by 0x46E46DD: QTextEngine::shapeLine(QScriptLine const&) (qtextengine.cpp:844)
==30930== by 0x45C34D3: QPainter::drawText(QPointF const&, QString const&, int, int) (qpainter.cpp:5669)
==30930== by 0x45C3A8A: QPainter::drawText(QPointF const&, QString const&) (qpainter.cpp:5642)
==30930== by 0x804A5DB: vdCam::save(QString const&, QString const&, int, bool, double, bool, bool, QVector<vdCam_text> const&) (in /mnt/data/Data/Leon/Code/C++/vdCam/vdCam)
==30930== by 0x804C4B3: main (in /var/vdCam/vdCam)

De code voor het tekenen van de tekst komt hier op neer:
C++:
1
2
3
4
5
6
7
8
// painter is QPainter object,  tmp is een QImage object (al met data)
painter.begin(&tmp);

painter.setPen(QPen(QColor("#FF0000")));

painter.setFont(QFont("Arab", 12, QFont::Bold, false));

painter.drawText(0, 0, text); // Hier gaat het fout


Het probleem ligt niet aan de painter object zelf, namelijk als ik drawLine doe gaat het wel gewoon goed. Is dit een bug in Qt 4.5 of doe ik gewoon iets fout? Ik heb zelf niets kunnen vinden over deze error. In alle voorbeelden doen ze het namelijk ook zo... :S

Acties:
  • 0 Henk 'm!

  • igmar
  • Registratie: April 2000
  • Laatst online: 03-09 22:58

igmar

ISO20022

Aan de stacktrace te zien pakt ie de foute overloaded functie, en ziet ie de 0 als een pointerwaarde. De 0x4 bevestigd dat eigenlijk wel :) Ik zou die 0 eens expliciet naar een int casten, en kijken wat ie dan doet.

Acties:
  • 0 Henk 'm!

  • corné
  • Registratie: Juni 2002
  • Laatst online: 14-11-2024
Of probeer
C++:
1
painter.drawText(QPointF(0.0, 0.0), text);

Acties:
  • 0 Henk 'm!

  • Stukfruit
  • Registratie: Oktober 2007
  • Niet online
Welke type heeft je text-variabele en hoe zet je daar je tekst in?

[ Voor 30% gewijzigd door Stukfruit op 24-03-2009 13:57 ]

Dat zit wel Schnorr.


Acties:
  • 0 Henk 'm!

  • vdvleon
  • Registratie: Januari 2008
  • Laatst online: 08-06-2023
Text is een QString, zoals de functie vraagt. Ik heb de QPointF(0.0, 0.0) geprobeerd, maar deze lukt ook niet.
De var text (QString) krijg ik via de commandline (argv). text = argv[n];

Ik krijg nog steeds de programma crash :S Als ik dit zo zie nog steeds zelfde fout melding.

Acties:
  • 0 Henk 'm!

  • EddoH
  • Registratie: Maart 2009
  • Niet online

EddoH

Backpfeifengesicht

Hoe maak je je QString aan en hoe vul je deze met data?
Ik gok dat tekst naar ongeldige mem locatie wijst.

Acties:
  • 0 Henk 'm!

  • Stukfruit
  • Registratie: Oktober 2007
  • Niet online
Oh ja, tuurlijk is het een QString :P sorry, niet goed gekeken.

Maar wat ik meer bedoelde is of je 'm wel goed vult. Heb je het al geprobeerd zonder die aanroep naar setFont?

Dat zit wel Schnorr.


Acties:
  • 0 Henk 'm!

  • vdvleon
  • Registratie: Januari 2008
  • Laatst online: 08-06-2023
Met de volgende code krijg ik nog steeds dezelfde fout:
C++:
1
2
3
const char* test = "test";
QString test2(test);
painter.drawText(QPointF(0.0, 0.0), test2);

Acties:
  • 0 Henk 'm!

  • EddoH
  • Registratie: Maart 2009
  • Niet online

EddoH

Backpfeifengesicht

eeeh....
moet je de argumenten niet by reference geven?

[ Voor 10% gewijzigd door EddoH op 24-03-2009 19:12 ]


Acties:
  • 0 Henk 'm!

  • vdvleon
  • Registratie: Januari 2008
  • Laatst online: 08-06-2023
@EddoH
Wat bedoel je hier mee precies?

Ik heb nu het volgende (in mijn echte code is het iets anders):
C++:
1
2
3
4
5
6
7
8
// ...
QPainter painter(&img); // img is een QImage object
QPen pen("#FF0000");
painter.setPen(pen);
QFont font("courier", 12, QFont::Bold, true);
painter.setFont(font);
QString text("text");
painter.drawText(0, 0, test);


Hier komt het op neer. img word wel goed door gegeven, want als ik de drawLine functie gebruik gaat het wel goed. Ik kom er maar niet uit :S

Acties:
  • 0 Henk 'm!

  • EddoH
  • Registratie: Maart 2009
  • Niet online

EddoH

Backpfeifengesicht

Ik heb niet even de docs bij de hand, maar voor zover ik me kan herrinneren geef je het adres van je QString mee aan de drawText methode?
Dus '&test' ipv 'test'. Maar dit zou dan al niet moeten compilen lijkt me...

Waar je naar moet zoeken is iig een reference (adres dus) die niet geldig is.
Post graag je exacte code, ipv 'iets wat er op lijkt', aangezien er in je echte implementatie een fout kan zitten..

Acties:
  • 0 Henk 'm!

  • VyperX
  • Registratie: Juni 2001
  • Laatst online: 14-08 13:04
[url="http://doc.trolltech.com/4.5/qpainter.html#drawText-12"]void QPainter::drawText ( int x, int y, const QString & text )[/url]


Oftewel, de text wordt by-reference doorgestuurd naar de functie. Geen & nodig ervoor.

Volgens de specificatie is het een overloaded convenience functie. Aan je stacktrace te zien wordt uiteindelijk de variant
void QPainter::drawText ( const QPointF & position, const QString & text )
gebruikt.

Wat dat betreft lijkt het niet aan jouw aanroep te liggen, maar iets wat dieper in Qt zit dat misgaat... Misschien dat het font zelf niet gevonden/ingeladen kan worden? (Guessing here.)
EddoH schreef op woensdag 25 maart 2009 @ 08:55:
...
Waar je naar moet zoeken is iig een reference (adres dus) die niet geldig is.
...
Euh, dat is nou juist het mooie van een reference, die is altijd geldig (tenzij je ranzige dingen gaat doen als het dereferencen van ongeinitialiseerde pointers).

My Dwarf Fortress ASCII Reward: ~~@~~####,.".D",.B""


Acties:
  • 0 Henk 'm!

  • EddoH
  • Registratie: Maart 2009
  • Niet online

EddoH

Backpfeifengesicht

Ok, meende me te herrinneren dat functie een pointer verwachtte(en dus klopt m'n by-reference opmerking ook niet :P) , negeer mn vorige opmerking dus.

Ik wil nog steeds graag even de exacte code zien. Je kan ervan uitgaan dat eht niet aan QT ligt, ik ben nog nooit een bug in QT tegengekomen, in ieder geval niet bij deze triviale dingen.

PS) zeggen dat een reference altijd geldig is is wel heel eng ViperX .....

Acties:
  • 0 Henk 'm!

  • VyperX
  • Registratie: Juni 2001
  • Laatst online: 14-08 13:04
Ik heb hier even een testje gedraaid en de code (zoals je hier eerder poste) werkt bij mij wel. (Naja, nadat ik m'n QImage had omgezet naar QImage::Format_RGB32, ipv Indexed8...)
EddoH schreef op woensdag 25 maart 2009 @ 09:48:
...
PS) zeggen dat een reference altijd geldig is is wel heel eng ViperX .....
offtopic:
True, is een beetje kort door de bocht. Wat ik bedoelde is dat je een reference altijd moet initialiseren met een bestaand object of pointer... Zolang dat object blijft bestaan, blijft je reference geldig. Ik ga er wel van uit dat zijn QImage object dus bestaat en blijft bestaan gedurende de functie aanroep.

My Dwarf Fortress ASCII Reward: ~~@~~####,.".D",.B""


Acties:
  • 0 Henk 'm!

  • vdvleon
  • Registratie: Januari 2008
  • Laatst online: 08-06-2023
De image object is nu wel idd geen RGB32 maar RGB888 (dus 3 x een 8 bits integer (r, g en b) in plaats van 4 x 8 bits (r, g, b en a (alpha)). Ik zou kijken of dit het probleem oplost... nee, dit is het niet.

Ik post wel me hele code (wat mij relevant lijkt):

Ik heb een functie in de vdCam class, toImage(). Deze functie maakt een nieuwe QImage (pointer) aan en vult deze daarna pixel voor pixel met de data die ik via de opencv library uit de webcam haal:
C++:
1
2
QImage* qimg = new QImage(frame->width, frame->height, QImage::Format_RGB32); // RGB 4 * 8 Bits (rgba)
// Fill: foreach x: foreach y   qimg->setPixel(x, y, qRgb(r, g, b)) // ...


Deze functie word aangeroepen door de save functie:
C++:
1
bool vdCam::save(const QString &filename, const QString &type, int quality, bool inverse, double scale, bool mirror_hor, bool mirror_ver, const QVector<vdCam_text>& texts);


Ik gebruik de vdCam class om een programma te maken die verschillenden dingen kan. als eerste natuurlijk een foto maken via de webcam. Vervolgens kan je kiezen hoe veel fotos je wilt maken. Dus 1, en dan stoppen, of 10 achter elkaar. En dat kan je ook nogs een herhalen (door een oneindige loop). Dit word allemaal bepaald (en de 10 achter elkaar en de loop) via het main programma.

De save functie krijgt het volgende binnen:
- filename = waar moet ik de afbeelding opslaan
- type = als wat moet ik hem opslaan (jpg, png, etc.)
- quality = welke qualiteid (100%, 75%, etc.)
- inverse = moet er de inverse (van de kleuren) genomen worden?
- scale = de scale factor (vergroting/verkleining)?
- mirror_hor = horizontaal spiegelen?
- mirror_ver = verticaal spiegelen?
- texts = (belangrijk) dit is een lijst (Vector) van een vdCam_text struct. Hierin staat hoe de tekst aan de afbeelding toegevoegd moet worden:

C++:
1
2
3
4
5
6
7
8
9
10
struct vdCam_text{
    QString text;
    QString color;
    QString font;
    QString weight;
    bool italic;
    int x;
    int y;
    int size;
};


In de save functie worden de verschillende inputs afgehandeld:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
QImage* qimg = toImage();
QImage tmp = *qimg; // werkt makkelijker met sommige functie zoals mirrored (geeft namelijk een nieuwe QImage object terug)

// Bewerkingen: mirror, scale, etc.
// ...

// Het tekst gedeelte:
if(texts.size()>0){
    for(i=0; i<texts.size(); i++){
        // Begin painter
        QPainter painter(&tmp);
        
        // Color
        QPen pen(QColor(texts[i].color));
        painter.setPen(pen);
        
        // Font, size and style
        weight = QFont::Normal;
        if(texts[i].weight=="light")            weight = QFont::Light;
        else if(texts[i].weight=="normal")      weight = QFont::Normal;
        else if(texts[i].weight=="deminold")    weight = QFont::DemiBold;
        else if(texts[i].weight=="bold")        weight = QFont::Bold;
        else if(texts[i].weight=="black")       weight = QFont::Black;
        QFont font(texts[i].font, texts[i].size, weight, texts[i].italic);
        painter.setFont(font);
        
        // Get text
        text = texts[i].text;
        
        // Functions?
        // Kijk d.m.v. regex of tekst geen functie is zoals now() (voor datum, etc.)
        
        // Draw text
        if(painter.isActive()){
            // Draw
            painter.drawText(texts[i].x, texts[i].y, text);
        }
        
        // End painter
        painter.end();
    }
}

// Save image
bool result = tmp.save(filename, type.toStdString().c_str(), quality);
    
// Destroy qimg
delete qimg;
qimg = NULL;


Maak ik hier ergens een grote denk fout dan?

Acties:
  • 0 Henk 'm!

  • vdvleon
  • Registratie: Januari 2008
  • Laatst online: 08-06-2023
@ ViperX

Zelfs met deze simpele code krijg ik de zelfde foutmelding: Access not within mapped region at address 0x4
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <QImage>
#include <QPainter>

int main(int argc, char* argv[]){
    // QImage, painter test
    QImage qimg(500, 500, QImage::Format_RGB32);
    qimg.fill(qimg.depth());
    QPainter p(&qimg);
    p.drawText(0, 0, "test");
    p.end();
    qimg.save("test.jpg", "JPG", 100);
    
    // Exit
    return 0;
}


Ik ben toch bang dat mijn Qt 4.5 (linux) library het niet goed doet.

[EDIT]
Ik heb hem net ook gecompiled met de 4.5 (windows) library. Daar krijg ik ook een programma crash. Ik denk dat ik dan toch een fout heb gevonden in 4.5 ?

[ Voor 13% gewijzigd door vdvleon op 25-03-2009 17:19 ]


Acties:
  • 0 Henk 'm!

  • EddoH
  • Registratie: Maart 2009
  • Niet online

EddoH

Backpfeifengesicht

Je code lijkt correct.

ik kan het niet voor je testen aangezien ik hier alleen beschikking heb over Qt2.3, en in die versie is een QImage geen QPaintdevice...

Wat ik wel vreemd vind is dat het VyperX wel lukt om de code te draaien.
Een bug in Qt sluit ik nog steeds uit, dit is echt een triviaal stuk code, en zou als het een bug was vast en zeker aan het licht gekomen zijn.

gebruik je verschillende libs door elkaar oid?

Acties:
  • 0 Henk 'm!

  • vdvleon
  • Registratie: Januari 2008
  • Laatst online: 08-06-2023
Die test van mijn vorige post, die heb ik letterlijk zo gecompiled, gebruikte ik, zoals je kunt zien, geen andere library. Om hem te compilen gebruikte ik qmake met het bijbehorende .pro bestand:

code:
1
SOURCES += test.cpp


Dus niets ongewoons. Dus ik verwacht dan toch dat er in de 4.5 een bug zit...

[EDIT]
Ik heb net de zelfde source ook getest op een Debian Qt 4.4.3 systeem, zelfde fout. Misschien doe ik toch zelf iets fout... maar wat? :S Volgens mij houd ik me toch echt aan de voorbeelden die worden gegeven op internet.. Maar het is idd wel raar dat het VyperX wel lukt. Ik heb het nu op 3 verschillende pc's getest:
- Ubuntu Qt 4.5
- Window Qt 4.5 (met de Qt qmake en make)
- Debian Qt 4.4.3
Bij allemaal heb ik de zelfde korte test code gecompiled en hetzelfde .pro bestand gebruikt. En bij alle 3 lukt het niet :S

[EDIT2]
Ik denk dat ik de oorzaak gevonden heb. Maar hoe ik het moet oplossen weet ik nog niet. Namelijk de volgende code crash ook gewoon:
[code=c++]
QFontDatabase fonts;
QStringList fonts_list = fonts.families();
std::cout << fonts_list.join("|").toStdString() << "\n";
[code]
Of te wel, het laden van de Fonts lukt gewoon niet. Als ik deze 3 regels compile op Window, crasht het programam niet, maar geeft hij ook geen fonts weer.

[ Voor 66% gewijzigd door vdvleon op 25-03-2009 23:38 ]


Acties:
  • 0 Henk 'm!

  • vdvleon
  • Registratie: Januari 2008
  • Laatst online: 08-06-2023
Ik heb het gefixed!!! Eindelijk. Wat een eigenlijk rare fout in Qt. Maar als je niet voor dat je de QPainter class gebruikt, QApplication aanroept (eerste regel Main functie is gebruikelijk) worden de fonts niet (goed) geladen. En, idd, de Format_RGB32 was ook nodig. Ik heb beide wel verandert, maar niet tegelijkerteid waardoor hij toch nog vast liep.

Hier is een voorbeeld te zien: http://vdvleon.xs4all.nl/cam/
Voor deze cam gebruik ik de volgende command:

code:
1
./vdCam /path/to/www/cam.jpg JPG 75 -deviceid 0 -loop 2000 -scale 2.5 -text 190 234 "date(dd-MM-yyyy hh:mm:ss)" "font=arial;italic;color=#FFFFFF;size=10" -text 180 24 "FCU|" "size=12;color=#FF0000;font=Cortoba" -text 218 24 "VDVLeon" "color=#FFFFFF;size=12;font=Cortoba" -text 290 24 "|NL" "color=blue;size=12;font=Cortoba"


Ik heb dus d.m.v. 4 -text opties deze tekst kunnen maken. Omdat FCU|VDVLeon|NL (mijn Call of Duty clan name) in 3 kleuren is, moet je dus de tekst in 3 stukjes toevoegen (en uitlijnen). Niet super netjes, maar het werkt. En je start de cam prog toch maar 1 x op.

Ik ben tevreden! :P

Bedankt voor jullie hulp allemaal.

Acties:
  • 0 Henk 'm!

  • EddoH
  • Registratie: Maart 2009
  • Niet online

EddoH

Backpfeifengesicht

Goed dat het gefixt is.
QApplication niet aanroepen kan inderdaad voor 'rare' (maar uiteindelijk verklaarbare:P) problemen zorgen.
Had op zich alleen wel een debug melding vanuit Qt verwacht
Pagina: 1