我正在研究一种尝试使用CPLEX解决数学问题的算法,并且由于某些指针的错误,我得到了一些错误的答案。因此,我尝试使用valgrind来跟踪问题并解决问题,不幸的是我设法追踪内存泄漏但无法找到如何修复它们。 因此,我将向您提供与问题相关的代码的所有部分以及当前的valgrind错误,以及希望某人能够提供帮助。为了让您简要了解该算法的实际情况,该算法实际上是一个更大问题的子问题,子问题是最小流量成本问题(http://en.wikipedia.org/wiki/Minimum-cost_flow_problem),程序是从主要数据中收到一些信息后初始化子问题的一部分问题是构造节点,弧,边界和成本以及所有其他适当的信息,然后使用求解器类来解决问题。 希望以下代码出价和评论将帮助您了解正在发生的事情:
1)问题初始化功能(无输入或输出): {
/*parameters used for the initialazation,fUCProblemInstance is a class connected with the main problem which is used to pass informations to the sub problem */
const Index horizonLen = fUCProblemInstance->GetHorizonLen();
const Index numNodes = horizonLen + 1;
const Index numArcs = horizonLen * 3;
/*MCFCplex() is the class of the solver and fMCFClass is a pointer to the class MCFClass which is a general class containing general information (virtual functions, indexes, etc) for all the possible solvers of the subproblems, except from MCFCplex there are 3 more possible solvers with different classes, */
fMCFClass = new MCFCplex();
/* basic initialization of values for the nodes (starting,ending), the bounds, the deficits and the size of the problem*/
fDualSolution.fHydroDuals.Resize(numNodes, numNodes);
tFlows upperBounds(numArcs, F_INF);
tFlows deficits(numNodes, 0);
tNodes startingNodes(numArcs, InINF);
tNodes endingNodes(numArcs, InINF);
Index i;
// Seting arcs
fFirstA2 = numNodes-1;
fLastA2 = 2*(numNodes-1);
fFirstA3 = 2*(numNodes-1);
fLastA3 = 3*(numNodes-1);
for (i=0; i<numNodes-1; ++i)
{
assert (startingNodes[i]==InINF);
assert (endingNodes[i]==InINF);
assert (startingNodes[i + fFirstA2]==InINF);
assert (endingNodes[i + fFirstA2]==InINF);
assert (startingNodes[i + fFirstA3]==InINF);
assert (endingNodes[i + fFirstA3]==InINF);
startingNodes[i] = i; // A_1 arcs
endingNodes[i] = i+1;
startingNodes[i + fFirstA2] = i; // A_2 arcs
endingNodes[i + fFirstA2] = numNodes-1;
startingNodes[i + fFirstA3] = i; // A_3 arcs
endingNodes[i + fFirstA3] = numNodes-1;
}
// Seting deficits
deficits[0] = -(fHydroUnit->GetInitialFlood() + fHydroUnit->GetInflow()[0]);
deficits[horizonLen] += -deficits[0];
for (i=1; i<horizonLen; ++i)
{
deficits[i] = -fHydroUnit->GetInflow()[i];
deficits[horizonLen] += -deficits[i];
}
// Adjust lower bound scaling
deficits[0] += fHydroUnit->GetMinFlood();
deficits[horizonLen] -= fHydroUnit->GetMinFlood();
// Setting upperbounds (and lowerbounds)
for (i=0; i<horizonLen; ++i)
{
upperBounds[i] = fHydroUnit->GetMaxFlood() - fHydroUnit->GetMinFlood();
upperBounds[i + horizonLen] = fHydroUnit->GetMaxUsage();
upperBounds[i + 2*horizonLen] = fHydroUnit->GetMaxSpillage();
}
/*After the initialization of all the parts the solver is also initialized in function LoadNet*/
fMCFClass->LoadNet(numNodes, numArcs, numNodes, numArcs,
&upperBounds[0], NULL, &deficits[0],
&startingNodes[0], &endingNodes[0]);
}
2)求解器的初始化函数:
void MCFCplex::LoadNet( cIndex nmx , cIndex mmx , cIndex pn , cIndex pm ,
cFRow pU , cCRow pC , cFRow pDfct , cIndex_Set pSn ,
cIndex_Set pEn )
{
// allocating and deallocating memory- - - - - - - - - - - - - - - - - - - -
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
if( ( mmax && nmax ) && ( ( nmx != nmax ) || ( mmx != mmax ) ) ) {
MemDeAlloc();
nmax = mmax = 0;
}
if( ( mmx && nmx ) && ( ( nmx != nmax ) || ( mmx != mmax ) ) ) {
nmax = nmx;
mmax = mmx;
MemAlloc();
}
if( ( ! nmax ) || ( ! mmax ) ) // just sit down in the corner and wait
return;
// now setting up data - - - - - - - - - - - - - - - - - - - - - - - - - - -
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
n = pn;
m = pm;
// setup data structures for arc creation/deletion- - - - - - - - - - - - -
VectAssign( ArcPos , FNumber( 0 ) , FreePos = m );
VectAssign( ArcPos + m , FNumber( Inf<FNumber>() ), mmax - m );
#endif
// create and set up temporary data structures - - - - - - - - - - - - - - -
int* stn = new int[ m ];
int* enn = new int[ m ];
for( Index i = m ; i-- ; ) {
stn[ i ] = pSn[ i ] MINUSONE;
enn[ i ] = pEn[ i ] MINUSONE;
}
double* sup = new double[ n ];
if( pDfct )
VectMAssign( sup , pDfct , n ); // invert the sign of deficits
else
VectAssign( sup , double( 0 ) , n );
double* upc = new double[ m ];
if( pU )
for( Index i = m ; i-- ; )
if( pU[ i ] == Inf<FNumber>() )
upc[ i ] = CPX_INFBOUND;
else
upc[ i ] = double( pU[ i ] );
else
VectAssign( upc , CPX_INFBOUND , m );
double* obj = new double[ m ];
if( pC )
for( Index i = m ; i-- ; )
if( pC[ i ] == Inf<CNumber>() ) {
#if( DYNMC_MCF_CPX )
ArcPos[ i ] = pU[ i ];
#endif
obj[ i ] = upc[ i ] = 0;
}
else
obj[ i ] = double( pC[ i ] );
else
VectAssign( obj , double( 0 ) , m );
// load internal structure of Cplex- - - - - - - - - - - - - - - - - - - - -
status = CPXNETcopynet( env , net , CPX_MIN , n , sup , NULL , m , stn ,
enn , NULL , upc , obj , NULL );
assert( ! status );
// setup QP data - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
qp = NULL; // problem is initially Network
QPMthd = qpNSimplex; // set default QP solving method to Network Simplex
// delete temporaries- - - - - - - - - - - - - - - - - - - - - - - - - - - -
delete[] obj;
delete[] upc;
delete[] sup;
delete[] enn;
delete[] stn;
status = MCFClass::kUnSolved;
} // end( MCFCplex::LoadNet )
loadnet中使用的函数:
template<class T1, class T2>
static inline void VectMAssign( T1 *g1 , const T2 *g2 , MCFCplex::Index n )
{
// g1 := - g2
for( ; n-- ; )
*(g1++) = - *(g2++);
}
template<class T>
static inline void VectAssign( T *const g , const T x , MCFCplex::cIndex n )
{
// g[ i ] = x for each i = 0 .. n - 1
for( T *tg = g + n ; tg > g ; )
*(--tg) = x;
}
void MCFCplex::MemAlloc( void )
{
// create a new Cplex problem- - - - - - - - - - - - - - - - - - - - - - - -
int ts;
net = CPXNETcreateprob( env , &ts , "NET" );
// create data structures for arc creation/deletion- - - - - - - - - - - - -
ArcPos = new FNumber[ mmax ];
// if necessary, resize static members - - - - - - - - - - - - - - - - - - -
if( mmax > nmaxarc ) {
if( nmaxarc ) {
delete[] ChangeUB;
delete[] val;
delete[] ind;
}
ind = new int[ nmaxarc = mmax ];
val = new double[ nmaxarc ];
ChangeUB = new char[ nmaxarc ];
VectAssign( ChangeUB , 'U' , nmaxarc );
}
} // end( MemAlloc )
/*--------------------------------------------------------------------------*/
void MCFCplex::MemDeAlloc( void )
{
delete[] ArcPos;
if( net )
CPXNETfreeprob( env , &net );
else {
CPXfreeprob( env , &qp );
delete[] Startn;
delete[] Endn;
}
} // end( MemDeAlloc )
然后使用函数解决问题:
void MCFCplex::SolveMCF( void )
{
if( net ) {
CPXNETprimopt( env , net ); // call the network simplex- - - - - - - - - -
status = CPXNETgetstat( env , net );
}
else {
CPXqpopt( env , qp ); // call the QP solver - - - - - - - - - - - - -
status = CPXgetstat( env , qp );
}
switch( status ) {
case( CPX_OPTIMAL ): status = MCFClass::kOK;
break;
case( CPX_INForUNBD ):
case( CPX_INFEASIBLE ): status = MCFClass::kUnfeasible;
break;
case( CPX_UNBOUNDED ): status = MCFClass::kUnbounded;
break;
default: status = MCFClass::kStopped;
}
} // end( MCFCplex::SolveMCF )
我在Valgrind得到的错误:
Invalid read of Size 8 [PID 963]:
by OX5522AA: CPXNETprimopt
by 0X4b17C0: MCFCplex::SolveMCF (MCFCPLEX.cpp:442)
.
.
. The path continues until it reaches the main function from where function is originally called
所以我跟踪了打印出来的问题的根源:
Adress 0x66ed440 is 16 bytes after a block of size 192 free'd [PID: 2024]
at 0x4C2AF50: operator delete[](void*)(vg_replace_malloc.c:537)
by 0x4302FA: MCFCplex::Loadnet(unsigned int, unsigned int, unsigned int, unsigned int, double const*, double const*, double const*, unsigned int const*, unsigned int const*)(MCFCPLEX.cpp:442)
.
.
. The path continues until it reaches the main function from where function is originally called
当我在eclipse中使用valgrind工具时,我甚至得到一个指向大小为192的块之后16字节的指针,它显示了函数loadnet中删除数组obj的行:
delete[] obj;
所以这或多或少是我的问题,任何帮助都非常需要帮助,如果需要更多说明,请告诉我。