Memory Leak when looping over out-links of objects

Hi,

We think we've found a memory leak in DOORs 8.2 when looping over the out-links in objects. We haven't been able to find any other references to this problem (but, of course, we could be searching for the wrong terms).

Is this a known issue?

Many thanks,

Mike
mikebleazard - Thu May 31 18:47:11 EDT 2012

Re: Memory Leak when looping over out-links of objects
Mathias Mamsch - Thu May 31 20:46:54 EDT 2012

Memory leaks is DOORS is a complicated issue. Most of the time it is not obvious where the memory is leaked. When interating over links in DOORS, e.g. most of the time people forget to free the 'ModuleVersion':
 

Link L
for L in o->"*" do {
   ModuleVersion mv = targetVersion L 
   load (L, false) 
   // delete mv 
   Object oTgt = target L 
   ... 
}

 


I have used DOORS 8.2 for a very long time and I have successfully written scripts that will loop over the complete database iterating 7000000 links without running into memory problems. I really doubt that there is a memory leak in the native DOORS perms. Why do you think there is a memory leak for looping over out-links? Are you experiencing memory rise or slowdown? If you provide some code we can see, if we can spot the reason for your issues.
Maybe that helps, regards, Mathias

 

 


Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS

 

Re: Memory Leak when looping over out-links of objects
mikebleazard - Fri Jun 01 19:48:00 EDT 2012

Mathias Mamsch - Thu May 31 20:46:54 EDT 2012

Memory leaks is DOORS is a complicated issue. Most of the time it is not obvious where the memory is leaked. When interating over links in DOORS, e.g. most of the time people forget to free the 'ModuleVersion':
 

Link L
for L in o->"*" do {
   ModuleVersion mv = targetVersion L 
   load (L, false) 
   // delete mv 
   Object oTgt = target L 
   ... 
}

 


I have used DOORS 8.2 for a very long time and I have successfully written scripts that will loop over the complete database iterating 7000000 links without running into memory problems. I really doubt that there is a memory leak in the native DOORS perms. Why do you think there is a memory leak for looping over out-links? Are you experiencing memory rise or slowdown? If you provide some code we can see, if we can spot the reason for your issues.
Maybe that helps, regards, Mathias

 

 


Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS

 

Mathias,

Many thanks for your reply.

We did not realise that ModuleVersion needed to be freed. This isn't documented particularly well in the DXL Reference Manual (I don't think it's mentioned). And the DXL Reference Manual gives several examples using ModuleVersions where they're not deleted!

Now that we are deleting the ModuleVersions, we think this has improved the way our script is performing.

We suspect there might also be a problem when we switch a module into 'open for edit' that we already have 'open for read' - but we haven't had chance to properly investigate these suspicions yet,

Thanks again,

Mike

Re: Memory Leak when looping over out-links of objects
Mathias Mamsch - Sat Jun 02 17:43:56 EDT 2012

mikebleazard - Fri Jun 01 19:48:00 EDT 2012
Mathias,

Many thanks for your reply.

We did not realise that ModuleVersion needed to be freed. This isn't documented particularly well in the DXL Reference Manual (I don't think it's mentioned). And the DXL Reference Manual gives several examples using ModuleVersions where they're not deleted!

Now that we are deleting the ModuleVersions, we think this has improved the way our script is performing.

We suspect there might also be a problem when we switch a module into 'open for edit' that we already have 'open for read' - but we haven't had chance to properly investigate these suspicions yet,

Thanks again,

Mike

Hi Mike,

there is another complexity with ModuleVersions that you need to take care of, to have your program leak free. You need to make sure that you assign the ModuleVersion always in the declaration and not put the declaration outside the loop. Otherwise you will have a leak too.
 

...
ModuleVersion mv = targetVersion L    // no leak
delete mv 
...
// --------------------- snip --------------------
 
ModuleVersion mv = null 
...
mv = targetVersion L   // Leak!
delete mv
...

 


The reason is, that ModuleVersion has a copy - assignment operator declared:

 

 

ModuleVersion ::= (ModuleVersion &, ModuleVersion)



which will copy the ModuleVersion for each assignment. Fortunately another 'bug' in DOORS will make DXL not call the assignment operator when you use it in a declaration. So when you use mv = ... outside the declaration, the assignment operator will make a copy of the ModuleVersion and assign this copy to the variable mv.

Hope that will help to resolve the memory leaks completely.

You can use the following code to check the number of allocated objects in your loop to see, if the number of allocated objects increase inside the loop. If the number stays the same then you can be sure that you have no memory leak in your DXL code.



 

 

 

int *::+(int *ptr1, int ofs) { int *ptr2 = ptr1; ptr2+=ofs; return ptr2 }
int *::@(int *ptr, int ofs) { int ad = *(ptr + ofs); int *ptr2 = addr_ ad; return ptr2 }
 
int *ccp () {
    DB x = create ""
        int *p = addr_ x; int *r = p @ 48
        destroy x
        return r
}
 
int *mbn (int *cc) { return cc @ 0x74 }
int *dp (int *n) { return n @ 0 }
int *nn      (int *n) { return n @ 8 }
 
int allocatedObjects() {
   int cnt = 0
   int *mb = mbn ccp() 
   while (!null mb) { mb = nn mb; cnt++ }
   return cnt 
}
 
// ------------- snip ----------------
 
print "Allocated Objects at start of DXL code:" 
print allocatedObjects() 
 
Buffer buf = create() 
print "Allocated Objects after Allocating a Buffer:" 
print allocatedObjects() 
 
delete buf
print "Allocated Objects after Freeing the Buffer:" 
print allocatedObjects()



Hope that will help you getting rid of all memory leaks. Regards, Mathias



 

 

 


Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS

 

Re: Memory Leak when looping over out-links of objects
Mathias Mamsch - Thu Jun 07 09:57:32 EDT 2012

Mathias Mamsch - Sat Jun 02 17:43:56 EDT 2012

Hi Mike,

there is another complexity with ModuleVersions that you need to take care of, to have your program leak free. You need to make sure that you assign the ModuleVersion always in the declaration and not put the declaration outside the loop. Otherwise you will have a leak too.
 

...
ModuleVersion mv = targetVersion L    // no leak
delete mv 
...
// --------------------- snip --------------------
 
ModuleVersion mv = null 
...
mv = targetVersion L   // Leak!
delete mv
...

 


The reason is, that ModuleVersion has a copy - assignment operator declared:

 

 

ModuleVersion ::= (ModuleVersion &, ModuleVersion)



which will copy the ModuleVersion for each assignment. Fortunately another 'bug' in DOORS will make DXL not call the assignment operator when you use it in a declaration. So when you use mv = ... outside the declaration, the assignment operator will make a copy of the ModuleVersion and assign this copy to the variable mv.

Hope that will help to resolve the memory leaks completely.

You can use the following code to check the number of allocated objects in your loop to see, if the number of allocated objects increase inside the loop. If the number stays the same then you can be sure that you have no memory leak in your DXL code.



 

 

 

int *::+(int *ptr1, int ofs) { int *ptr2 = ptr1; ptr2+=ofs; return ptr2 }
int *::@(int *ptr, int ofs) { int ad = *(ptr + ofs); int *ptr2 = addr_ ad; return ptr2 }
 
int *ccp () {
    DB x = create ""
        int *p = addr_ x; int *r = p @ 48
        destroy x
        return r
}
 
int *mbn (int *cc) { return cc @ 0x74 }
int *dp (int *n) { return n @ 0 }
int *nn      (int *n) { return n @ 8 }
 
int allocatedObjects() {
   int cnt = 0
   int *mb = mbn ccp() 
   while (!null mb) { mb = nn mb; cnt++ }
   return cnt 
}
 
// ------------- snip ----------------
 
print "Allocated Objects at start of DXL code:" 
print allocatedObjects() 
 
Buffer buf = create() 
print "Allocated Objects after Allocating a Buffer:" 
print allocatedObjects() 
 
delete buf
print "Allocated Objects after Freeing the Buffer:" 
print allocatedObjects()



Hope that will help you getting rid of all memory leaks. Regards, Mathias



 

 

 


Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS

 

Due to a question in this post: https://www.ibm.com/developerworks/forums/thread.jspa?threadID=430318&tstart=0

I will elaborate on the ModuleVersion issue here. You can run the following code (from an open Module):
 

if (null current Module) error "Please run this script from a module!"
 
print "Allocated Objects Before Assigning in Declaration: " allocatedObjects() "\n"
ModuleVersion mv = moduleVersion current
print "Allocated Objects After Assigning in Declaration " allocatedObjects() "\n"
delete mv 
print "Allocated Objects After Deleting the assignment in Declaration " allocatedObjects() "\n"
 
print "\n"
 
print "Allocated Objects Before Assigning Outside of Declaration: " allocatedObjects() "\n"
ModuleVersion mv2 
mv2 = moduleVersion current
print "Allocated Objects After Assigning Outside of Declaration " allocatedObjects() "\n"
delete mv2 
print "Allocated Objects After Deleting the assignment Outside of Declaration " allocatedObjects() "\n"

 


which gives you the following output:

 

 

Allocated Objects Before Assigning in Declaration: 0
Allocated Objects After Assigning in Declaration 1
Allocated Objects After Deleting the assignment in Declaration 0
 
Allocated Objects Before Assigning Outside of Declaration: 0
Allocated Objects After Assigning Outside of Declaration 2
Allocated Objects After Deleting the assignment Outside of Declaration 1



getting the allocatedObjects() function from the above post.

The code you posted does not resolve the problem, since the problem comes not from the targetVersion function. It comes as soon as you assign the ModuleVersion to some variable. If you had the functions defined as in your post then you have the same behaviour:



 

 

 

ModuleVersion mv = targetVersionOfLink L  // no leak 
ModuleVersion mv2; mv2 = targetVersionOfLink L  // leak



So you need to be aware, that whereever you assign a ModuleVersion outside a declaration you will make a copy. The workaround is not doing it. Or deleting the original ModuleVersion afterwards (which you can't if you are calling a native DOORS perm that returns a ModuleVersion). You could define a new assignment operator that will copy the value differently of course,e.g.:



 

 

 

 

ModuleVersion ::<- (ModuleVersion &mv, ModuleVersion mv2) {
    int &ref = addr_ mv  // cast to integer
    int val  = addr_ mv2 // cast to integer
    ref = val  // use integer assignment to make a reference copy ...
    return mv2
}
 
ModuleVersion mv3
mv3 <- moduleVersion current



Hope that will shed a little more light onto the issue. Regards, Mathias



 

 

 


Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS