1

I have a class named Jellyfish who use the singleton design pattern :

jellyfish.h

#ifndef JELLYFISH_H
#define JELLYFISH_H

#include <QHash>
#include <QScriptEngine>

class QScriptValue;

class Jellyfish : public QObject
{

    public:

         static Jellyfish * getInstance();
         static Jellyfish * instance;

    private:

        Jellyfish();

};

#ifndef

jellyfish.cpp

Jellyfish * Jellyfish::instance = NULL;

Jellyfish * Jellyfish::getInstance()
{

    if ( !Jellyfish::instance )
    {
        Jellyfish::instance = new Jellyfish();
    }

    return Jellyfish::instance;

}

When I am in main.cpp and make tests, I have no errors:

main.cpp

#include <QApplication>

#include "jellyfish.h"

class Jellyfish;

int main( int argc, char *argv[] )
{

    QApplication app( argc, argv );

    Jellyfish *toto = Jellyfish::getInstance();
    Jellyfish *toto2 = Jellyfish::getInstance();
    Jellyfish *toto3 = Jellyfish::getInstance();

    return app.exec();

}

But I want to use some static methods in Jellyfish in external QScript files :

jellyfish.h

private:

    static QScriptValue set( QScriptContext *context, QScriptEngine *engine );
    QScriptEngine *script_engine;

jellyfish.cpp

Jellyfish::Jellyfish()
{

    script_engine = new QScriptEngine;

    /* ... */

    initScriptEngine();

}

void Jellyfish::initScriptEngine()
{

    QScriptValue object = script_engine->newQObject( this );

    object.setProperty( "set", script_engine->newFunction( set ) );

    script_engine->globalObject().setProperty( "jellyfish", object );

}

QScriptValue Jellyfish::set( QScriptContext *context, QScriptEngine *engine )
{

    // I have to load instance because I am in a static method.
    // But this is where the application loop endlessly.
    Jellyfish *jellyfish = Jellyfish::getInstance();
    return true;

}

And finaly the parsed script:

jellyfish.set( "line_numbers",  true );

Problem

When I run the application, getInstance() always creates a new Jellyfish instance. But the real problem is that on the output with debug (qDebug() << "test";) I can see that the application loop on Jellyfish::getInstance(); until I get a sgmentation fault.

Could someone help me to understand this ?

MARTIN Damien
  • 996
  • 2
  • 15
  • 36
  • it would be easier to read the code if it was continuous, not split. could it be that the 'set' method should be non-static? – Rudolf Mühlbauer Oct 14 '12 at 19:13
  • set have to be static (if it is not, Qt seems not be able to detect it) : `src/jellyfish.cpp:43:64: erreur: no matching function for call to ‘QScriptEngine::newFunction()’` But maybe I missunderstood (I'm new in Qt devlopement). cf. http://doc.qt.digia.com/qt/qscriptvalue.html#setProperty – MARTIN Damien Oct 14 '12 at 19:18

1 Answers1

1

It is because your Jellyfish constructor call itself recursively!

Break your program in debugger and you will see backtrace like this:

   ...
   Jellyfish::Jellyfish()
   Jellyfish::getInstance()
   Jellyfish::set
   Jellyfish::initScriptEngine() 
   Jellyfish::Jellyfish()
   Jellyfish::getInstance()

The problem is that your constructor calls Jellyfish::getInstance(), but when object is constructed the Jellyfish::instance is still NULL:

Jellyfish * Jellyfish::getInstance()
{

    if ( !Jellyfish::instance )
    {
        // this line
        // Jellyfish::instance = new Jellyfish();
        // is equivalent to
        Jellyfish * temp = new Jellyfish(); // *
        Jellyfish::instance = temp; // not NULL after construction
    }

    return Jellyfish::instance;

}

If you call getInstance() from your constructor then it will always result in infinite recursion (until segfault). The only one solution is to call Jellyfish::initScriptEngine() not from your constructor - but explicit:

   Jellyfish::getInstance()->initScriptEngine();
PiotrNycz
  • 23,099
  • 7
  • 66
  • 112