Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Out of Memory - ActiveX exe

Status
Not open for further replies.

mpdillon

Programmer
Jan 27, 2004
18
0
0
US
Hi,
I have written an ActiveX exe. It is used by another Standard exe and several other VBA applications. When the standard exe uses the AxtiveX exe over and over again, a "Run-time error '7';Out of memory" error occurs.
Stepping through the program and watching the windows process monitor I can see the memory increase each time the ActiveX exe is called.
I have tried setting the object which references the ActiveX exe in the Standard exe to nothing as soon as control is returned to the Standard exe but this does not have any affect.
How do I prevent the calls to the ActiveX exe from using additional memory on each call?
It takes a while to load the ActiveX exe on the first call so I would prefer not to remove it from memory. Rather I would like to reuse it on the next call without the memory penalty.

thanks,
pat

What is being processed - The Standard exe compiles information on a product. It then passes the information to the ActiveX exe which produces a document. Control is returned to the Standard exe and another product is processed.
 
Are you sure that the ActiveX exe is releasing all of the objects it allocates before it ends?

Tracy Dryden

Meddle not in the affairs of dragons,
For you are crunchy, and good with mustard. [dragon]
 
I may not understand your question. I close all connections and recordsets. I set them all to nothing. I hide all forms and set the forms equal to nothing. Is this what you mean by releasing objects?
thanks,
pat
 
Yup, that's what I meant. There are other objects that you might be using as well. Look for anything allocated as "New", or anything assigned using "Set".

Tracy Dryden

Meddle not in the affairs of dragons,
For you are crunchy, and good with mustard. [dragon]
 
I'm getting that the problem is with the ActiveX exe, not with the clients. I would start by investigating the methods that are called. I would attempt to isolate the method that is causing the error, and also examine the call stack at the beginning and end of the method. You may have some sort of unintended recursive proc call.

HTH

Bob
 
Is it truly your intent to repeatedly create a new running instance of this ActiveX EXE? You might check whether you have the right instancing attributes set on the class you're creating out of it.

As I recall there are three things that will keep an ActiveX EXE running:

Client references to objects served out of the EXE.
Loaded forms.
Running code.

Most ActiveX EXEs aren't constructed to have long-running code on their own process (e.g. code running out of Sub Main). The most common culprit would probably be a class in the ActiveX EXE that loads a form and leaves it loaded.
 
<Is it truly your intent to repeatedly create a new running instance of this ActiveX EXE?

I didn't think of the instancing attribute. The OP hasn't implied one way or the other, of course.

Just to be clear, Pat: SingleUse means that each client creates a new copy of the EXE (uses its own copy), whereas MultiUse means that all clients use the same instance of it (use a shared copy). Your behavior suggests SingleUse, and probably one of the "things" that dilettante mentions.

If you're trying to create some sort of asynchronous behavior, there are certainly ways that you can keep the exe from shutting down without intending to.

Bob
 
First,First, I want to thank everyone for the clarity of their explanations. And as I expected you all knew what my problem was before I did. I will list what I found so others can use it for reference.

The Class module in the ActiveX exe is call by the client program. In turn the Class module opens and closes many forms within the ActiveX exe. The ActiveX exe always exits through the same subroutine and the same Class module that were initially called. My problem was forms left in memory. I added this code at the end of the subroutine.

Dim frm as Form ‘Put this at the top

For each frm in Forms
Unload frm
Set frm = nothing
Doevents
Next frm

‘I also made sure my data connections and recordsets were cleared
On Error Resume Next
rs1.close
set rs1 = nothing
pdbData.Close ‘ADO connection
set pdbData = nothing
On error GoTo 0

I decided it might be possible that the Class might end abnormally. I used the Class_Terminate subroutine for this purpose. I added the frm code above to the Class_Terminate subroutine.

That cleared up the memory issue. However, I went through my client application and added I added a set OBJECT = nothing when I wanted to clear the object I was using to call the Class of the AcitveX exe.
In some instances I didn’t want to reload the ActiveX exe so I didn’t set it to nothing. When the client would process some information and need to print a form using the ActiveX exe I would not set the ActiveX exe equal to nothing until all the forms were printed. The client successfully used the ActiveX exe over 2500 times before I set the ActiveX exe equal to nothing. There wasn’t any excessive memory usage during this time.
Thanks again for your help
I want to thank everyone for the clarity of the exp
 
Congratulations on fixing your problem! A couple of suggestions for further improvement:

Iterating through the forms collection to unload open forms is fine when you know what forms you're unloading. It isn't fine as a means of correcting a logical error in your existing code, where you forgot to unload the form. That sort of habit will lead to unnecessary maintenance overhead in the long run. If you are using this as a means of not finding where you have a form left open unintentionally, I encourage you to find the source of the error and correct it there.

Using On Error Resume Next to leave errors unhandled also leads to maintenance overhead. In effect, you're turning a potential runtime error into a potential logical error. You're better off finding out what causes the error and anticipating it. In the case you have above:
Code:
If rs1.State = adStateOpen then
   rs1.Close
End If
is to be preferred, and even then it's important to know the circumstances under which recordsets hitting this code are open and those under which they aren't.

<I hide all forms and set the forms equal to nothing.
Looking back over your posts, I find this. Hiding a form doesn't remove it from memory. Unloading does. Setting form variables equal to nothing just makes the variable no longer refer to the form.

To clarify how all this works, put a msgbox in each of the following events: Intialize, Load, Unload, and Terminate. (If you want to, you could check Activate, Paint and Resize as well.) Now, do each of these, in isolation from one another (do each separately, not one after the other):
1. create a form variable and set it to a new Form1.
2. set a property on form1.
3. Load form1.
4. Show form1.
5. Hide form1.
6. Unload form1.
7. set a form variable that you set in 1 to nothing.

Think of other stuff, and also check the Forms.Count property. You may find this exercise as informative as I did when I did it.

HTH

Bob
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top