C ++ Class Destroyer Called in the middle of the code

1

I'm getting a bit deeper into using C ++, and I'm having a hard time migrating an application that uses callbacks and a singleton to manage settings.

While initializing the code still in the main function, I create the singleton responsible for maintaining the settings (CycloConfig) and I have an auxiliary function that functions as callback of a graphical interface that calls the correct function of another class according to certain actions of the user interface, and so changes some settings that will be used.

So far so good, but when I run the application, in the part when I do not use more functions that are setting values in the main function the destructor is being called. but the configuration class will still be used inside the callback which means it is used at any time to set new values and this values are read simultaneously in a loop in the main function.

I've already tried putting the destructor at the end of the code when the main function ends, just before the return calling it config. ~ CycloConfig (); and have already taken code optimization parameters.

But even so it still destroys the object when I no longer use it to set values in the main function. Although you need to read the values that were updated by the callback.

The created object of class CycloConfig is not passed as a parameter, since it is a singleton and can not be instantiated. only obtained through a factory method:

CycloConfig& CycloConfig::get() {
#if __cplusplus < 201103L
#warning "Este código é seguro com o uso do C+11, pode haver problemas relativo a concorrencia em verões inferiores."
#endif
    static CycloConfig instance;
    return instance;
}

Callback:

void MouseCallback(int event, int x, int y,
        int __attribute__((__unused__)) flags,
        void __attribute__((__unused__)) *data) {
    CycloConfig config = CycloConfig::get();
    static InteractionHandler ih(config.getAddress());
    if (ih.hasCurrentCallbackFunction()) {
        switch (event) {
        case (cv::EVENT_LBUTTONDOWN):
            ih.callCurrentCallBack(x, y);
            ih.nextStep();
            break;
        default:
            //printf("Error: MouseCallback: event = %d\n", event);
            //exit(EXIT_FAILURE);
            break;
        }
    }
}

Starting the main function:

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

    unsigned long debug = 1;

    std::cout << "*****************************************************"
            << std::endl;
    std::cout << "** Obtendo configurações                           **"
            << std::endl;
    CycloConfig config = CycloConfig::get();
    std::cout << "** configurações carregadas                        **"
            << std::endl;
    std::cout.flush();
...

End of Primary Function:

...

    delete cap;
    if (outputDevice)
        delete outputDevice;
    if (outputFile)
        delete outputFile;

    config.~CycloConfig();
    exit(0);
    return 0;
}

Build Class builders and destructors:

CycloConfig::CycloConfig() {
    this->LoadData();
    std::cout << "** CycloConfig> Criado." << std::endl;
}

CycloConfig::~CycloConfig() {
    this->PersistData();
    std::cout << "** CycloConfig> Descartado." << std::endl;

}
...
class CycloConfig {
private:
    const char *configFile = "CycloTracker.conf";
    ConfigData data;

    CycloConfig();

public:
    virtual ~CycloConfig();

    void PersistData();
    void LoadData();

    static CycloConfig& get();
    
asked by anonymous 08.10.2016 / 08:54

1 answer

2

Your problem lies in the way you are accessing your singleton object. The access function is correctly returning the object by reference, but both the MouseCallback function and the main are being declared "normal" object variables, which end up generating copies of it. And by the time these copies go out of scope they are destroyed, causing the destructor to be called.

The simple solution is to just change the declaration of local variables to a reference type, or pointer:

CycloConfig config = CycloConfig::get(); //Cópia

CycloConfig &config = CycloConfig::get(); //Referência

CycloConfig *config = &CycloConfig::get(); //Ponteiro

C ++ primarily treats user-defined objects in the same way as the basic types of language. Then, similarly, if there was a function returning a reference to a int and its value was assigned to a local variable, this variable is a copy, completely independent of the original reference.

For simple types, destruction is trivial and copying is done by simple bit replication, but for user-defined types, destructors, copy constructors, and assignment operators can be defined. If they are not defined, the compiler automatically generates them. But for singletons and other special cases, you can suppress this generation:

class CycloConfig {
    ....
    //Desabilita Construtor de Cópia gerado pelo compilador
    CycloConfig(const CycloConfig &) = delete;

    //Desabilita Operador de Atribuição gerado pelo compilador
    CycloConfig &operator=(const CycloConfig &) = delete;
    ....
};

In this way, if you try to copy the object inadvertently (as happened in the problem), the compiler will prevent, warning that copy operations have been disabled by the user.

    
08.10.2016 / 09:43