Seite 1 von 1

Runtime Error mit Opengl

Verfasst: 4. August 2011 08:14
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

Re: Runtime Error mit Opengl

Verfasst: 4. August 2011 08:25
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.

Re: Runtime Error mit Opengl

Verfasst: 4. August 2011 09:41
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.

Re: Runtime Error mit Opengl

Verfasst: 4. August 2011 18:53
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..

Re: Runtime Error mit Opengl

Verfasst: 5. August 2011 08:19
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:

Re: Runtime Error mit Opengl

Verfasst: 5. August 2011 08:55
von solarix
Bewirkt mein erster Hinweis (connect zu updateGL()) nichts?

Re: Runtime Error mit Opengl

Verfasst: 5. August 2011 12:43
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^^