Runtime Error mit Opengl

Alles rund um die Programmierung mit Qt
Antworten
zx7r
Beiträge: 13
Registriert: 26. Mai 2010 20:16
Wohnort: Berlin

Runtime Error mit Opengl

Beitrag von zx7r »

Morgen,

ich habe in meinem Projekt ein Opengl-Modul eingebettet und seitdem stürzt mein Programm regelmäßig ab nach ein paar Stunden.
Ich weiß einfach nicht woran es liegen kann. Ich gebe alloziierten Speicherplatz immer wieder frei. Die Meldung, die Qt beim Absturz in der Konsole ausgibt ist folgende:
QPainter::end: Painter ended with 3 saved states
QWidget::repaint: Recursive repaint detected
QPainter::end: Painter ended with 3 saved states
QWidget::repaint: Recursive repaint detected
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
terminate called recursively
Ich könnte mir vorstellen, dass es ein Speicherzugriffsfehler ist. So ist es doch auch aus dem Meldung zu entnehmen, oder?
Gibt es von Sysinternals o.ä. ein Tool, um solche Sachen zu analysieren?

Bitte um Hilfe bei diesem Fehler. Das Problem ist, dass ich mein Programm immer über Nacht auf Arbeit laufen lasse und erst am nächsten morgen den Absturz feststellen kann.

Vielen Dank im Vorraus!

Gruß zx7r
ich möchte die 64-bit Farbpalette als Buntstiftsammlung
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Re: Runtime Error mit Opengl

Beitrag von franzf »

Code: Alles auswählen

QWidget::repaint: Recursive repaint detected
Sagt doch schon alles, oder?
Hast du irgendwo in einem paintEvent() ein repaint() stehen?
Rekursion ohne Abbruch führt irgendwann dazu, dass kein Speicher mehr zu Verfügung steht. Die nächst SPeicheranforderung führt dann zu einem std::bad_alloc.
zx7r
Beiträge: 13
Registriert: 26. Mai 2010 20:16
Wohnort: Berlin

Re: Runtime Error mit Opengl

Beitrag von zx7r »

Vielen Dank für die schnelle Antwort! Ich habe einen Timer am laufen, der repaint() aufruft. Der Code ist folgender. Ich habe mit Opengl gerade einmal angefangen und mache das wahrscheinlich nicht gerade wie man es soll. Naja mal schauen. Also der Code ist folgender:

Code: Alles auswählen

#include "openglmodell.h"
#include <QDebug>

OpenGlModell::OpenGlModell(QWidget *parent) :
        QGLWidget(parent),
        assayList(),
        substrat(),
        timer(),
        substratExists(false)
{
    timer = new QTimer();
    connect(timer, SIGNAL(timeout()), this, SLOT(timerSlot()));
    timer->start(50);
}

void OpenGlModell::timerSlot()
{
    repaint();
}

// Initialisiert die Zeichenfläche
void OpenGlModell::initializeGL()
{
    glShadeModel(GL_SMOOTH);
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClearDepth(1.0f);							// Depth Buffer Setup
    glEnable(GL_DEPTH_TEST);						// Enables Depth Testing
    glEnable(GL_POLYGON_SMOOTH);
    glEnable(GL_POLYGON_SMOOTH_HINT);
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);			// Really Nice Perspective Calculations
}

// Stellt die Größe der Zeichenfläche ein
void OpenGlModell::resizeGL(int w, int h)
{
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0f, w/h, 0.1f,100.0f);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

// Zeichnet auf der Zeichenfläche
void OpenGlModell::paintGL()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);			// Clear The Screen And The Depth Buffer
    glLoadIdentity();							// Reset The Current Modelview Matrix

    //    glBegin(GL_LINES);   						// X-Achse
    //    glColor3f(1.0f,1.0f,1.0f);
    //    glVertex3f(-10.0f, 0.0f, -1.0f);
    //    glVertex3f(10.0f, 0.0f, -1.0f);
    //    glEnd();
    //    glBegin(GL_LINES);   						// Y-Achse
    //    glColor3f(125.0f,125.0f,0.0f);
    //    glVertex3f(0.0f, -10.0f, -1.0f);
    //    glVertex3f(0.0f, 10.0f, -1.0f);
    //    glEnd();

    glTranslatef(0.0f,-5.0f,-25.0f);

    GLUquadric *oben    = gluNewQuadric();
    GLUquadric *hl      = gluNewQuadric();
    GLUquadric *mitte   = gluNewQuadric();
    GLUquadric *ec      = gluNewQuadric();
    GLUquadric *unten   = gluNewQuadric();
    GLUquadric *shutter = gluNewQuadric();
    GLUquadric *sub     = gluNewQuadric();

    if(substratExists)
    {
        glPushMatrix();
        /*Substrat*/
        glTranslatef(0.0f,12.0f,-15.0f);            // Move Right And Into The Screen
        glRotatef(20,1.0f,0.0f,0.0f);               // Rotate The Cube On X, Y & Z
        glBegin(GL_QUADS);                          // Start Drawing The Cube
        glColor3f(0.39f,0.52f,0.55f);               // Set The Color To Green
        glVertex3f( 3.0f, 0.5f,-1.0f);              // Top Right Of The Quad (Top)
        glVertex3f(-3.0f, 0.5f,-1.0f);              // Top Left Of The Quad (Top)
        glVertex3f(-3.0f, 0.5f, 1.0f);              // Bottom Left Of The Quad (Top)
        glVertex3f( 3.0f, 0.5f, 1.0f);              // Bottom Right Of The Quad (Top)

        glVertex3f( 3.0f,-0.5f, 1.0f);              // Top Right Of The Quad (Bottom)
        glVertex3f(-3.0f,-0.5f, 1.0f);              // Top Left Of The Quad (Bottom)
        glVertex3f(-3.0f,-0.5f,-1.0f);              // Bottom Left Of The Quad (Bottom)
        glVertex3f( 3.0f,-0.5f,-1.0f);              // Bottom Right Of The Quad (Bottom)
        glColor3f(0.33f,0.44f,0.46f);               // Set The Color To Red
        glVertex3f( 3.0f, 0.5f, 1.0f);              // Top Right Of The Quad (Front)
        glVertex3f(-3.0f, 0.5f, 1.0f);              // Top Left Of The Quad (Front)
        glVertex3f(-3.0f,-0.5f, 1.0f);              // Bottom Left Of The Quad (Front)
        glVertex3f( 3.0f,-0.5f, 1.0f);              // Bottom Right Of The Quad (Front)

        glVertex3f( 3.0f,-0.5f,-1.0f);              // Bottom Left Of The Quad (Back)
        glVertex3f(-3.0f,-0.5f,-1.0f);              // Bottom Right Of The Quad (Back)
        glVertex3f(-3.0f, 0.5f,-1.0f);              // Top Right Of The Quad (Back)
        glVertex3f( 3.0f, 0.5f,-1.0f);              // Top Left Of The Quad (Back)

        glVertex3f(-3.0f, 0.5f, 1.0f);              // Top Right Of The Quad (Left)
        glVertex3f(-3.0f, 0.5f,-1.0f);              // Top Left Of The Quad (Left)
        glVertex3f(-3.0f,-0.5f,-1.0f);              // Bottom Left Of The Quad (Left)
        glVertex3f(-3.0f,-0.5f, 1.0f);              // Bottom Right Of The Quad (Left)

        glVertex3f( 3.0f, 0.5f,-1.0f);              // Top Right Of The Quad (Right)
        glVertex3f( 3.0f, 0.5f, 1.0f);              // Top Left Of The Quad (Right)
        glVertex3f( 3.0f,-0.5f, 1.0f);              // Bottom Left Of The Quad (Right)
        glVertex3f( 3.0f,-0.5f,-1.0f);              // Bottom Right Of The Quad (Right)

        glEnd();                                    // Done Drawing The Quad

        /*Shutterstange*/
        glColor3f(0,1,1);
        glBegin(GL_LINES);
        glVertex3f(3.1,-0.7,-0.5);
        glVertex3f(3.1,0.5,-0.5);
        glEnd();
        glPopMatrix();

        /*Substrat Shutter*/
        glPushMatrix();
        glTranslatef(3.1f,11.2f,-15.0f);
        glRotatef(20,1.0f,0.0f,0.0f);
        glRotatef(180-substrat->getRotation(),0.0f,1.0f,0.0f);
        glTranslatef(3.1f,0.0f,0.0f);
        glRotatef(90,1.0f,0.0f,0.0f);
        glBegin(GL_POLYGON);
        gluQuadricDrawStyle(sub, GLU_FILL);
        glColor3f(0,1,1);
        gluDisk(sub, 0, 3.2, 360, 60);
        glEnd();
        glPopMatrix();
    }

    foreach(Element *el, assayList){
        /*oben*/
        glPushMatrix();
        glRotatef((GLfloat) el->getAngle(),0.0f,0.0f,1.0f);
        glRotatef(90,1.0f,0.0f,0.0f);
        glTranslatef((GLfloat) el->getPosX(),0.0f,0.0f);

        glBegin(GL_POLYGON);
        gluQuadricDrawStyle(oben, GLU_LINE);
        glColor3f(0,0,240);
        gluCylinder(oben, 0.5, 0.5, 1, 36, 5);
        glEnd();
        glPopMatrix();

        /*HL*/
        glPushMatrix();
        glRotatef((GLfloat) el->getAngle(),0.0f,0.0f,1.0f);
        glRotatef(90,1.0f,0.0f,0.0f);
        glTranslatef((GLfloat) el->getPosX(),0.0f,1.0f);

        glBegin(GL_POLYGON);
        gluQuadricDrawStyle(hl, GLU_LINE);
        glColor3f(255,0,0);
        gluCylinder(hl, 0.5, 0.5, 0.25, 36, 5);
        glEnd();
        glPopMatrix();

        /*Mitte*/
        glPushMatrix();
        glRotatef((GLfloat) el->getAngle(),0.0f,0.0f,1.0f);
        glRotatef(90,1.0f,0.0f,0.0f);
        glTranslatef((GLfloat) el->getPosX(),0.0f,1.25f);

        glBegin(GL_POLYGON);
        gluQuadricDrawStyle(mitte, GLU_LINE);
        glColor3f(0,0,240);
        gluCylinder(mitte, 0.5, 0.5, 1, 36, 5);
        glEnd();
        glPopMatrix();

        /*EC*/
        glPushMatrix();
        glRotatef((GLfloat) el->getAngle(),0.0f,0.0f,1.0f);
        glRotatef(90,1.0f,0.0f,0.0f);
        glTranslatef((GLfloat) el->getPosX(),0.0f,2.25f);

        glBegin(GL_POLYGON);
        gluQuadricDrawStyle(ec, GLU_LINE);
        glColor3f(255,0,0);
        gluCylinder(ec, 0.5, 0.5, 0.25, 36, 5);
        glEnd();
        glPopMatrix();

        /*Unten*/
        glPushMatrix();
        glRotatef((GLfloat) el->getAngle(),0.0f,0.0f,1.0f);
        glRotatef(90,1.0f,0.0f,0.0f);
        glTranslatef((GLfloat) el->getPosX(),0.0f,2.5f);

        glBegin(GL_POLYGON);
        gluQuadricDrawStyle(unten, GLU_LINE);
        glColor3f(0,0,240);
        gluCylinder(unten, 0.5, 0.5, 1, 36, 5);
        glEnd();
        glPopMatrix();

        /*Bezeichnung der Quelle*/
        glColor3f(1,1,1);
        if(el->getPosX() > 0)
            renderText((GLfloat) el->getPosX()*1.1, -5.0f, -1.0f, el->getAssay());
        else
            renderText((GLfloat) el->getPosX()*1.1 - 1, -5.0f, -1.0f, el->getAssay());

        /*Shutterstange*/
        glPushMatrix();
        glRotatef((GLfloat) el->getAngle(),0.0f,0.0f,1.0f);
        if(el->getPosX()<0)
            glTranslatef((GLfloat) el->getPosX()-0.55f,0.1f,-0.1f);
        else
            glTranslatef((GLfloat) el->getPosX()+0.55f,0.1f,-0.1f);
        glRotatef(90,1.0f,0.0f,0.0f);
        glBegin(GL_LINES);
        glColor3f(0,255,255);
        glVertex3f(0,0,0);
        glVertex3f(0, 0, 3.6);
        glEnd();
        glPopMatrix();

        /*Shutter*/
        glPushMatrix();

        glRotatef((GLfloat) el->getAngle(),0.0f,0.0f,1.0f);
        if(el->getPosX()<0)
            glTranslatef((GLfloat) el->getPosX()-0.55f,0.1f,-0.1f);
        else
            glTranslatef((GLfloat) el->getPosX()+0.55f,0.1f,-0.1f);
        glRotatef(el->getRotation(),0.0f,1.0f,0.0f);
        if(el->getPosX()<0)
            glTranslatef(0.6f,0.0f,0.0f);
        else
            glTranslatef(-0.6f,0.0f,0.0f);
        glRotatef(90,1.0f,0.0f,0.0f);

        glBegin(GL_POLYGON);
        gluQuadricDrawStyle(shutter, GLU_FILL);
        glColor3f(0,255,255);
        gluDisk(shutter, 0, 0.6, 360, 60);
        glEnd();
        glPopMatrix();
    }

    // Speicherplatz wieder freigeben
    gluDeleteQuadric(oben);
    gluDeleteQuadric(hl);
    gluDeleteQuadric(mitte);
    gluDeleteQuadric(ec);
    gluDeleteQuadric(unten);
    gluDeleteQuadric(shutter);
    gluDeleteQuadric(sub);
}

// fügt ein Substrat auf die Zeichenfläche hinzu
void OpenGlModell::setSubstrate(QString tAssay, bool tOpen)
{
    delete substrat;
    substrat = new Element(tAssay, 0, tOpen);
    substratExists = true;
}

// fügt eine Quelle auf die Zeichenfläche hinzu
void OpenGlModell::addAssay(QString tAssay, bool tOpen)
{
    switch(assayList.size()){
    case 0:
        assayList.append(new Element(tAssay, -1, tOpen));
        break;
    case 1:
        assayList.append(new Element(tAssay, 1, tOpen));
        break;
    case 2:
        assayList.append(new Element(tAssay, -4, tOpen));
        break;
    case 3:
        assayList.append(new Element(tAssay, 4, tOpen));
        break;
    case 4:
        assayList.append(new Element(tAssay, -7, tOpen));
        break;
    case 5:
        assayList.append(new Element(tAssay, 7, tOpen));
        break;
    default:
        break;
    }
}

// verändert die Shutterstellung einer Quelle
void OpenGlModell::setShutterPos(QString &tAssay, bool tOpen)
{
    if(substratExists)
    {
        if(tAssay == substrat->getAssay())
        {
            substrat->setShutterPos(tOpen);
            return;
        }
    }
    foreach(Element *el, assayList)
    {
        if(el->getAssay() == tAssay)
        {
            el->setShutterPos(tOpen);
            return;
        }
    }
}

// Schließt einen Schutter mit der Bezeichnung "tAssay"
void OpenGlModell::closeShutter(QString tAssay)
{
    this->setShutterPos(tAssay, false);
}

// Öffnet einen Schutter mit der Bezeichnung "tAssay"
void OpenGlModell::openShutter(QString tAssay)
{
    this->setShutterPos(tAssay, true);
}

// ändert die Position eines Shutters
void OpenGlModell::posChangedSlot(QString tAssay, bool tPos)
{
    if(tPos)
        this->openShutter(tAssay);
    else
        this->closeShutter(tAssay);
}
Das repaint() rufe ich in der Methode auf, um neue Positionen zu zeichnen.
ich möchte die 64-bit Farbpalette als Buntstiftsammlung
solarix
Beiträge: 1133
Registriert: 7. Juni 2007 19:25

Re: Runtime Error mit Opengl

Beitrag von solarix »

Die Rekursion sehe ich nicht auf Anhieb, aber sicher ist, dass man mit "updateGL()" connected und nicht "repaint()" aufruft:

Code: Alles auswählen

connect(timer, SIGNAL(timeout()), this, SLOT(updateGL()));
http://doc.qt.nokia.com/latest/qglwidget.html#updateGL

hth..


[EDIT]
Die Quadrics würde ich übrigens einmalig (ausserhalb der paintGL-Methode) erzeugen/zerstören.. das in jedem Durchgang zu machen ist nicht sehr performant..

[EDIT2]
Generell solltest du prüfen, ob du das nicht mit DisplayLists (http://wiki.delphigl.com/index.php/Displaylisten) schneller/eleganter erledigen könntest..
zx7r
Beiträge: 13
Registriert: 26. Mai 2010 20:16
Wohnort: Berlin

Re: Runtime Error mit Opengl

Beitrag von zx7r »

Danke für die Hinweise!

Ich habe das Erstellen/Zerstören ausgelagert. Ist auf jeden Fall besser, das stimmt! Mit den Displaylists habe ich noch nie etwas gemacht, klingt aber gut. ich werde es mir mal anschauen.

Aber zu meinem eigentlichen Problem, wo da nun eine Rekursion entstehen soll hast du kein Vorschlag, oder? Ich sehe es einfach nicht... Das ist mein Problem :cry:
ich möchte die 64-bit Farbpalette als Buntstiftsammlung
solarix
Beiträge: 1133
Registriert: 7. Juni 2007 19:25

Re: Runtime Error mit Opengl

Beitrag von solarix »

Bewirkt mein erster Hinweis (connect zu updateGL()) nichts?
zx7r
Beiträge: 13
Registriert: 26. Mai 2010 20:16
Wohnort: Berlin

Re: Runtime Error mit Opengl

Beitrag von zx7r »

Hey, ja ich probiere es jetzt aus. Lasse das Programm wieder laufen und warte;-)
Mhh. Na ich melde mich dann in ca. 8 stunden wieder^^
ich möchte die 64-bit Farbpalette als Buntstiftsammlung
Antworten