C++ Class Destructor Called in the middle of code

Asked

Viewed 1,884 times

1

I’m getting deeper into the use of C++, and I’m having trouble migrating an application that uses callbacks and a Singleton to manage settings.

During code initialization still in main function, I create the Singleton responsible for the maintenance of the configurations (Cycloconfig) and I have an auxiliary function that works as a callback of a graphical interface that calls the correct function of another class according to certain user interface actions, and so changes some settings that will be used.

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

I tried to put the destructor at the end of the code when the main function ends, just before the Return calling it configo.~ Cycloconfig(); and I’ve already removed code optimization parameters.

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

The created object of the class CycloConfig is not passed as parameter since it is a Singleton and cannot 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;
        }
    }
}

Start of 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 Main Function:

...

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

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

Configuration Class Constructors 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();
  • There are very few occasions where you should call the destructor explicitly, and yours is not one of them. It is very likely that your object is being copied to be passed from parameter to some function, and this copy is being destroyed. Show a little code, mainly snippets that pass your Singleton as parameter or return. So it will be easier to give more concrete help.

  • Hello, I added some codes I hope they will be enough.

1 answer

2


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

The simple solution is just to 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 basic language types. So, in the same way, 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, to singletons and other special cases, it is possible to 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;
    ....
};

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

  • I used the reference option and the problem persists. I logged a step log: https://gist.github.com/carlosdelfino/26a9518c7c7e776ee3970d30bf6d74b7

  • @Delfino Already tried to change his class to "delete" copy operations?

  • How so? , on the link above the gist I put the main file where the problem occurs. he’s still pretty confused because I’m migrating and wiping the code bit by bit.

  • Look at the final part of the answer, I’ve made an update. Do what you have to do to ensure that copies are not being created anywhere else. Also you are still explicitly calling the destructor at the end of the main function, which is wrong.

  • the problem is solved. 100% Thanks.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.