[Cbc] Segfault / memory corruption after "assignSolver" in "CbcModel"

John Forrest john.forrest at fastercoin.com
Fri May 9 11:20:10 EDT 2014


Dirk,

Looking at the code, it looks like a bug/feature but probably not a good 
idea to try and fix.

CbcModel clones a clean copy of OsiSolverInterface so it can use it for 
heuristics and double checking a solution.  The solver passed to 
CbcModel gets chewed up and has cuts etc etc.  So at end it looks as if 
CbcModel says - better to get rid of that solver and replace with the 
clean one.  So getting model.solver() AFTER branchAndBound to pass to 
postprocessing is correct.  That solver then goes when model disappears.

John


On 09/05/14 15:37, Dirk Eßer wrote:
>
> Hi John,
>
> I read the documentation of "preProcessNonDefault" (where it says 
> "returns the new problem") and jumped to conclusions, which seem (in 
> retrospect) to not have been justified. Should have checked with 
> valgrind before posting to this list.
>
> Anyway, just out of curiosity: it is still not clear to me, who is 
> responsible for freeing the OsiSolverInterface instance returned by 
> "CglPreProcess::preProcessNonDefault". It's copy ("solver3" in my 
> original code) will be taken care of by "CbcModel::assignModel", but 
> the result of "preProcessNonDefault" ("solver2") looks like it is 
> leaked (though it isn't as the valgrind log shows).
>
> Regardless, thanks for the answer and sorry for the noise.
>
> Cheers,
> Dirk
>
>
>
>
> Am 09.05.2014 15:58, schrieb John Forrest:
>> Dirk,
>>
>> Not exactly sure where the problem was - I rearranged code a bit and 
>> it seems OK and without a leak.  See if it fixes.
>>
>> John Forrest
>> On 09/05/14 11:00, Dirk Eßer wrote:
>>> Hi John,
>>>
>>> thanks for the reply. I now have a minimal example (for some 
>>> definition of minimal, which you can find attached), with which I 
>>> can reproduce the access violation. Right now, it seems, that I have 
>>> the choice between
>>>
>>>   * getting a segfault when trying to clean-up all solvers
>>>     instanciated during the program run, or
>>>   * leaking a solver instance.
>>>
>>> I am not quite comfortable with option 2, since I don't know, how 
>>> much memory is actually leaked in this case, in particular as the 
>>> actual application will solve quite a few MIPs sequentially in the 
>>> same process. If it were only a couple of bytes per solver instance, 
>>> then I am almost willing accept that as "price to pay" for the 
>>> preprocessing step. But I don't know the inner workings of the 
>>> solvers involved enough to make a judgement here.
>>>
>>> Also, I am still not convinced, that the error isn't entirely in our 
>>> own code; right now, though, I don't see anything inherently wrong. 
>>> Any help appreciated.
>>>
>>>
>>> Cheers,
>>> Dirk Eßer
>>>
>>>
>>>
>>> Am 07.05.2014 19:36, schrieb John Forrest:
>>>> Dirk,
>>>>
>>>> The -cpp was a nice idea - but impossible to keep current - so 
>>>> something may be broken.
>>>>
>>>> Try using code from the Cbc/examples driver3.cpp or driver4.cpp 
>>>> which should give you the same flexibility.
>>>>
>>>> John Forrest
>>>> On 07/05/14 11:18, Dirk Eßer wrote:
>>>>> Hello,
>>>>>
>>>>> I have a little problem adding a preprocessing step to program 
>>>>> doing MIP solving using the CBC library. The problem is, that the 
>>>>> program fails with more or less random memory corruption (and in 
>>>>> the better cases: with a segfault) some of the time.
>>>>>
>>>>> The CbcModel instance is created programmatically
>>>>>
>>>>>     OsiClpSolverInterface iface;
>>>>>     CoinPackedMatrix pmx(false, num_columns, num_rows,
>>>>>     num_elements, matrix, columns, starts, lengths);
>>>>>
>>>>>     iface.setObjSense(-1.0);
>>>>>     iface.loadProblem(pmx, 0, 0, objective, senses, rights, 0);
>>>>>     iface.passInMessageHandler(&printer);
>>>>>
>>>>>     model_ptr LP(new CbcModel(iface));
>>>>>     ... adding stuff via LP->addObjects(...) to declare integer
>>>>>     constraints on variables and a few SOSes ...
>>>>>
>>>>> Things work fine, if we directly compute a solution without 
>>>>> further preprocessing via
>>>>>
>>>>>     LP->initialSolve();
>>>>>     LP->branchAndBound();
>>>>>
>>>>> We now try to add a pre-processing step to the solution process. 
>>>>> As a starting point, we used the driver code generated by the CBC 
>>>>> command line tool ("-cpp 0", which doesn't compile).
>>>>>
>>>>>     OsiSolverInterface* original_solver = LP->solver();
>>>>>     OsiSolverInterface* cloned_solver = original_solver->clone();
>>>>>     OsiSolverInterface* configured_solver = 0;
>>>>>
>>>>>     cloned_solver->passInMessageHandler(LP->messageHandler());
>>>>>     cloned_solver->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo);
>>>>>
>>>>>     CglPreProcess processor;
>>>>>
>>>>>                 {
>>>>>                     CglProbing prober;
>>>>>                     prober.setUsingObjective(1);
>>>>>                     prober.setMaxPass(3);
>>>>>     prober.setMaxProbeRoot(cloned_solver->getNumCols());
>>>>>                     prober.setMaxElements(100);
>>>>>                     prober.setMaxLookRoot(50);
>>>>>                     prober.setRowCuts(3);
>>>>>     processor.addCutGenerator(&prober);
>>>>>                 }
>>>>>
>>>>>     configured_solver =
>>>>>     processor.preProcessNonDefault(*cloned_solver, 2, 10);
>>>>>
>>>>>     cloned_solver->setHintParam(OsiDoInBranchAndCut, false,
>>>>>     OsiHintDo);
>>>>>
>>>>>     if (!configured_solver)
>>>>>     {
>>>>>         delete cloned_solver;
>>>>>         return status::infeasible;
>>>>>     }
>>>>>
>>>>>     configured_solver->setHintParam(OsiDoInBranchAndCut, false,
>>>>>     OsiHintDo);
>>>>>
>>>>>     OsiSolverInterface* configured_clone = configured_solver->clone();
>>>>>
>>>>>     LP->assignSolver(configured_clone, true /* Kill previous
>>>>>     solver */); /*-- XXX --*/
>>>>>     LP->initialSolve();
>>>>>     LP->branchAndBound();
>>>>>
>>>>>     int n_cols = cloned_solver->getNumCols();
>>>>>     processor.postProcess(*LP->solver());
>>>>>
>>>>>     LP->assignSolver(cloned_solver, true /* Kill previous solver */);
>>>>>     memcpy(LP->bestSolution(), LP->solver()->getColSolution(),
>>>>>     n_cols * sizeof(double));
>>>>>
>>>>> It seems, that we are violating one or two unwritten laws of 
>>>>> memory management with CBC, but I am at loss as what we are doing 
>>>>> wrong here. Any help, hints, pointer to documentation, etc. is 
>>>>> highly appreciated.
>>>>>
>>>>> Cheers,
>>>>> Dirk Eßer
>>>>>
>>>>>
>>>>> _______________________________________________
>>>>> Cbc mailing list
>>>>> Cbc at list.coin-or.org
>>>>> http://list.coin-or.org/mailman/listinfo/cbc
>>>>
>>>>
>>>>
>>>> _______________________________________________
>>>> Cbc mailing list
>>>> Cbc at list.coin-or.org
>>>> http://list.coin-or.org/mailman/listinfo/cbc
>>>
>>>
>>>
>>> _______________________________________________
>>> Cbc mailing list
>>> Cbc at list.coin-or.org
>>> http://list.coin-or.org/mailman/listinfo/cbc
>>
>>
>>
>> _______________________________________________
>> Cbc mailing list
>> Cbc at list.coin-or.org
>> http://list.coin-or.org/mailman/listinfo/cbc
>
>
>
> _______________________________________________
> Cbc mailing list
> Cbc at list.coin-or.org
> http://list.coin-or.org/mailman/listinfo/cbc

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://list.coin-or.org/pipermail/cbc/attachments/20140509/a30298d7/attachment-0001.html>


More information about the Cbc mailing list