Alex Dowling awdowlin at andrew.cmu.edu
Wed Jun 1 11:50:17 EDT 2011

```Kshitij,

Thank you for the prompt response.

Memory (de)allocation in Jac(...) is based on the sparse Jacobian example
included with ADOL-C. Below is a simplified version:

int Jac(...)
{

// Declare some variables not seen by ADOL-C

double *ud;
double *dud;

// Allocate memory for x and p
double *x = myalloc(NEQ+6);
double *p = myalloc(6);

// Populate ud and dud
// Code not shown in e-mail

int jac_nnz = 0;
int repeat = 0;
int options[4];

static unsigned int *jac_rind  = NULL;
static unsigned int *jac_cind  = NULL;
static  double *jac_values = NULL;

options[0] = 0;
options[1] = 0;
options[2] = 0;
options[3] = 0;

// Copy values from the inputs into x and p
// Code not shown in e-mail

tracerhs(t,x,dud,p);

// Calculate sparse Jacobian - Note: NEQ is a constant
rc = sparse_jac(1, NEQ, NEQ+6, repeat, x, &jac_nnz, &jac_rind, &jac_cind,
&jac_values, options);

// Copy values from jac_values into an input variable to this function
// Code not shown in e-mail

myfree(x);
myfree(p);

free(jac_rind);
free(jac_cind);
free(jac_values);

}

Is this the correct way to free the pointers used by ADOL-C?

I compiled everything with ColPack debug flag active. Valgrind is running
right now; it will take a while...

Alex Dowling

On Wed, Jun 1, 2011 at 7:13 AM, Kshitij Kulshreshtha <kshitij at math.upb.de>wrote:

> Hello Alex,
>
> ADOL-C (and also ColPack) follows the rule that any pointer that is the
> output of an ADOL-C function like jac_pat or sparse_jac, which gets
> allocated by ADOL-C but is returned to the user's code, should be
> deallocated by the user when he does not need it anymore.
>
> ADOL-C will not delete pointers that were given out to the user at any
> time. ADOL-C deallocates only the memory that it allocated internally
> and did not give out to the user.
>
> Please check that in your code all pointers that you get back from
> ADOL-C are deallocated by your code. Hopefully this should take care of
> loss records 3 and 105.
>
> I am not sure why you are getting so many string allocations. Strings
> are only used as constants inside ColPack as far as I see in the code.
> You should try to add -g in the FLAGS for building ColPack inside the
> common_variables.in file. This will enable line numbers inside ColPack
> code too, which will help debug better.
>
> As on 2011-06-01 01:17, Alex Dowling did write:
> > Hello everyone,
> >
> > Using valgrind I found a bunch of memory leaks with the Sparse Jacobian
> > features in ADOL-C. I noticed in the mailing list archives this problem
> > has been previously reported; The leaks still persist after I upgraded
> > to ADOL-C 2.2.0 and ColPack 1.0.3 today (the recommended action).
> >
> > Below is an excerpt of the valgrind report.
> >
> > ==21732==
> > ==21732== HEAP SUMMARY:
> > ==21732==     in use at exit: 29,627,156 bytes in 157,000 blocks
> > ==21732==   total heap usage: 229,529,359 allocs, 229,372,359 frees,
> > 762,459,196,535 bytes allocated
> > ==21732==
> > ==21732== 45 bytes in 1 blocks are possibly lost in loss record 2 of 105
> > ==21732==    at 0x4C28B42: operator new(unsigned long)
> > (vg_replace_malloc.c:261)
> > ==21732==    by 0x5413E6C: std::string::_Rep::_S_create(unsigned long,
> > unsigned long, std::allocator<char> const&) (in
> > /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.14)
> > ==21732==    by 0x5415904: char* std::string::_S_construct<char
> > const*>(char const*, char const*, std::allocator<char> const&,
> > std::forward_iterator_tag) (in
> > /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.14)
> > ==21732==    by 0x5415DF1: std::basic_string<char,
> > std::char_traits<char>, std::allocator<char> >::basic_string(char
> > const*, std::allocator<char> const&) (in
> > /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.14)
> > ==21732==    by 0x4C3DEF:
> > ColPack::BipartiteGraphPartialOrdering::ColumnSmallestLastOrdering() (in
> > /home/awdowlin/Documents/svn/research/ssPowerOptimTightBounds/debug)
> > ==21732==    by 0x4C4BB7:
> > ColPack::BipartiteGraphPartialOrdering::OrderVertices(std::string,
> > std::string) (in
> > /home/awdowlin/Documents/svn/research/ssPowerOptimTightBounds/debug)
> > ==21732==    by 0x47BEC8:
> >
> ColPack::BipartiteGraphPartialColoringInterface::PartialDistanceTwoColoring(std::string,
> > std::string) (in
> > /home/awdowlin/Documents/svn/research/ssPowerOptimTightBounds/debug)
> > ==21732==    by 0x47C9B3:
> >
> ColPack::BipartiteGraphPartialColoringInterface::GenerateSeedJacobian(double***,
> > int*, int*, std::string, std::string) (in
> > /home/awdowlin/Documents/svn/research/ssPowerOptimTightBounds/debug)
> > ==21732==    by 0x516721A: sparse_jac (sparsedrivers.cpp:314)
> > ==21732==    by 0x411BE5: Jac(int, double, _generic_N_Vector*,
> > _generic_N_Vector*, _DlsMat*, void*, _generic_N_Vector*,
> > _generic_N_Vector*, _generic_N_Vector*) (ss_model.c:364)
> > ==21732==    by 0x47606D: cvDenseSetup (cvodes_dense.c:269)
> > ==21732==    by 0x466228: cvStgrNlsNewton (cvodes.c:6561)
> > ==21732==
> > ==21732== 48 bytes in 1 blocks are possibly lost in loss record 3 of 105
> > ==21732==    at 0x4C28FAC: malloc (vg_replace_malloc.c:236)
> > ==21732==    by 0x515A679: indopro_forward_safe (uni5_for.c:1341)
> > ==21732==    by 0x5166016: jac_pat (sparsedrivers.cpp:91)
> > ==21732==    by 0x51670BF: sparse_jac (sparsedrivers.cpp:268)
> > ==21732==    by 0x411BE5: Jac(int, double, _generic_N_Vector*,
> > _generic_N_Vector*, _DlsMat*, void*, _generic_N_Vector*,
> > _generic_N_Vector*, _generic_N_Vector*) (ss_model.c:364)
> > ==21732==    by 0x47606D: cvDenseSetup (cvodes_dense.c:269)
> > ==21732==    by 0x465C10: cvNlsNewton (cvodes.c:6117)
> > ==21732==    by 0x467D88: cvStep (cvodes.c:5873)
> > ==21732==    by 0x469EA9: CVode (cvodes.c:3029)
> > ==21732==    by 0x41442E: eval_f_c(double*, double*, double*)
> > (ss_model.c:207)
> > ==21732==    by 0x4117BA: main (ssnew.c:146)
> > ==21732==
> > ==21732== 52 bytes in 1 blocks are possibly lost in loss record 4 of 105
> > ==21732==    at 0x4C28B42: operator new(unsigned long)
> > (vg_replace_malloc.c:261)
> > ==21732==    by 0x5413E6C: std::string::_Rep::_S_create(unsigned long,
> > unsigned long, std::allocator<char> const&) (in
> > /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.14)
> > ==21732==    by 0x5415904: char* std::string::_S_construct<char
> > const*>(char const*, char const*, std::allocator<char> const&,
> > std::forward_iterator_tag) (in
> > /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.14)
> > ==21732==    by 0x5415DF1: std::basic_string<char,
> > std::char_traits<char>, std::allocator<char> >::basic_string(char
> > const*, std::allocator<char> const&) (in
> > /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.14)
> > ==21732==    by 0x4C7FE6:
> >
> ColPack::BipartiteGraphPartialColoring::PartialDistanceTwoColumnColoring()
> > (in /home/awdowlin/Documents/svn/research/ssPowerOptimTightBounds/debug)
> > ==21732==    by 0x47C0D7:
> >
> ColPack::BipartiteGraphPartialColoringInterface::PartialDistanceTwoColoring(std::string,
> > std::string) (in
> > /home/awdowlin/Documents/svn/research/ssPowerOptimTightBounds/debug)
> > ==21732==    by 0x47C9B3:
> >
> ColPack::BipartiteGraphPartialColoringInterface::GenerateSeedJacobian(double***,
> > int*, int*, std::string, std::string) (in
> > /home/awdowlin/Documents/svn/research/ssPowerOptimTightBounds/debug)
> > ==21732==    by 0x516721A: sparse_jac (sparsedrivers.cpp:314)
> > ==21732==    by 0x411BE5: Jac(int, double, _generic_N_Vector*,
> > _generic_N_Vector*, _DlsMat*, void*, _generic_N_Vector*,
> > _generic_N_Vector*, _generic_N_Vector*) (ss_model.c:364)
> > ==21732==    by 0x47606D: cvDenseSetup (cvodes_dense.c:269)
> > ==21732==    by 0x466228: cvStgrNlsNewton (cvodes.c:6561)
> > ==21732==    by 0x46979C: cvStep (cvodes.c:6406)
> >
> > Note: Errors 5 through 105 are virtually the same.
> >
> > ==21732== 4,838,562 (95,232 direct, 4,743,330 indirect) bytes in 186
> > blocks are definitely lost in loss record 105 of 105
> > ==21732==    at 0x4C28B42: operator new(unsigned long)
> > (vg_replace_malloc.c:261)
> > ==21732==    by 0x516715C: sparse_jac (sparsedrivers.cpp:302)
> > ==21732==    by 0x411BE5: Jac(int, double, _generic_N_Vector*,
> > _generic_N_Vector*, _DlsMat*, void*, _generic_N_Vector*,
> > _generic_N_Vector*, _generic_N_Vector*) (ss_model.c:364)
> > ==21732==    by 0x47606D: cvDenseSetup (cvodes_dense.c:269)
> > ==21732==    by 0x465C10: cvNlsNewton (cvodes.c:6117)
> > ==21732==    by 0x467D88: cvStep (cvodes.c:5873)
> > ==21732==    by 0x469EA9: CVode (cvodes.c:3029)
> > ==21732==    by 0x41442E: eval_f_c(double*, double*, double*)
> > (ss_model.c:207)
> > ==21732==    by 0x4117BA: main (ssnew.c:146)
> > ==21732==
> > ==21732== LEAK SUMMARY:
> > ==21732==    definitely lost: 2,101,704 bytes in 3,135 blocks
> > ==21732==    indirectly lost: 27,442,563 bytes in 153,610 blocks
> > ==21732==      possibly lost: 35,785 bytes in 6 blocks
> > ==21732==    still reachable: 47,104 bytes in 249 blocks
> > ==21732==         suppressed: 0 bytes in 0 blocks
> > ==21732== Reachable blocks (those to which a pointer was found) are not
> > shown.
> > ==21732== To see them, rerun with: --leak-check=full --show-reachable=yes
> >
> > main, eval_f_c and Jac all refer to function I (or my predecessor) have
> > written. The functions beginning with cv belong to the numeric
> > integrator CVODES. ADOL-C is called in the function Jac.
> >
> > Are there any recommendations on resolving this issue? I'm happy to
> > help, but my C/C++ is a bit rusty.
> >
> > Alex Dowling
> >
> >
> >
> > _______________________________________________
>
> --
> Dr. Kshitij Kulshreshtha
>
> Institut für Mathematik,
> Warburger Straße 100,
>
> Büro: A3.235
>
> Privatanschrift:
> Arnikaweg 62