Question

Background: The C++ interface of IBM ILOG Cplex allocates and de-allocates memory rather unconventionally:

A declaration of an ILO environment IloEnv environment;, followed by a construction of models and solvers within this environment, followed by all these objects (including the environment) going out of scope results in a memory leak. Note that I have not used the new operator. One way to avoid this is to call environment.end(); before the object goes out of scope.

Setting: Now, I have a class whose purpose is to solve a specific ILP. This class has some member variables:

IloEnv ilpEnvironment_;
IloObjective ilpObjective_;
IloExpr ilpExpression_;
IloModel ilpModel_;
IloCplex ilpSolver_;
IloNumArray ilpSolution_;
IloNumVarArray ilpVariables_;
IloNumArray ilpStartValues_;
IloRangeArray constraints_; 

These member variables are initialized in the initializer list of the constructor:

inline MyClass::MyClass() 
:   ilpEnvironment_(),
    ilpObjective_(ilpEnvironment_),
    ilpExpression_(ilpEnvironment_),
    ilpModel_(ilpEnvironment_),
    ilpSolver_(ilpModel_),
    ilpSolution_(ilpEnvironment_),
    ilpVariables_(ilpEnvironment_),
    ilpStartValues_(ilpEnvironment_),
    constraints_(ilpEnvironment_)
{ /* ... */ }

The destructor de-allocates all the memory (that has been allocated by member functions of the class that operate on the member variables):

inline MyClass::~MyClass() {
    ilpEnvironment_.end();
}

Question: How do i implement a member function void clear() that de-allocates the memory and puts the class back into its initial state? Here are two rather naive attempts I made that don't work:

inline void MyClass::clear() {
    ilpEnvironment_.end();
    ilpEnvironment_ = IloEnv(); // does not work, whether or not I comment this line out
    ilpObjective_ = IloObjective(ilpEnvironment_);
    ilpExpression_ = IloExpr(ilpEnvironment_);
    ilpModel_ = IloModel(ilpEnvironment_);
    ilpSolver_ = IloCplex(ilpEnvironment_);
    ilpSolution_ = IloNumArray(ilpEnvironment_);
    ilpVariables_ = IloNumVarArray(ilpEnvironment_);
    ilpStartValues_ = IloNumArray(ilpEnvironment_);
    constraints_ = IloRangeArray(ilpEnvironment_);
}
Was it helpful?

Solution

If the purpose of the class is to solve a specific ILP model, then I would initialize the class with the model size/parameters, and create and destroy the CPLEX objects within a solve() member function while saving only the results as class members. Class members would be model parameters, and the object would keep all CPLEX dealings hidden.

You could even have a class member that keeps track of which constraints to activate in that particular solve() call.

If you absolutely have to use the CPLEX objects as changeable class members, then you might want to try to use object pointers as class members instead of the objects themselves. Calling IloEnv::end() destroys the objects associated with it, so you could call IloEnd::end() and then reassign the pointers to new objects.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top