TheSwamp

Code Red => AutoLISP (Vanilla / Visual) => Topic started by: sinc on August 02, 2004, 11:44:43 AM

Title: (vlax-release-object obj) vs (setq obj nil)
Post by: sinc on August 02, 2004, 11:44:43 AM
What's the difference between vlax-release-object and setq nil?  If I set a variable containing a vla-object to nil, is the vla-object released?  Or do I need to do an explicit vla-release-object?
Title: (vlax-release-object obj) vs (setq obj nil)
Post by: Jeff_M on August 02, 2004, 12:17:49 PM
From what I have read and experienced, you only need to use the vlax-release-object on symbols that were set with vlax-get-object, vlax-create-object, vlax-get-or-create-object or with the method "getinterfaceobject".
Title: (vlax-release-object obj) vs (setq obj nil)
Post by: JohnK on August 02, 2004, 12:36:23 PM
That is a very good question. I'll see if i cant find some references that will help explain it a bit more.

Its complicated and im prolly gonna expain this wrong, but heres a shot:

Basicly, when you 'nill out' a varialble you are just destroying the data in that variable ("setting it to zero's").

But whenyou release an object you are destroying a pointer and letting the computer know that it can claim that memeory space back.

...awe let me try to find some documentation on the subject.
Title: (vlax-release-object obj) vs (setq obj nil)
Post by: JohnK on August 02, 2004, 01:31:30 PM
I cant find anything usefull on the subject so im gonna try my hand at explaining it agian.

Ok, A variable is basically nothing more then a name associated with a value in a chunk of memory. In a procedural language (like AutoLisp) this all you have. However in an Object Orientated Language (Like C++ ...Visual Lisp is a crude OOP language.) you can have pointers. (Pointers are address' for that chunk of memory associated with a value. --Their use and importance isn't important at this time, just remember that they are diff. One is a name for a value and the other is an address for the memory chunk for a value.)

When you invoke a "VLAX-REALEASE..." you are telling the computer to dump that address and make the memory available to you again. (Theoretically you can reuse that same amount of memory right away, but that will almost never happen.) It doesn’t destroy the "object" but the memory for that object.
-For example:
(setq myobj (MAKE A VLX-OBJECT))
(DO SOME STUFF)
(VLAX-RELEASE THAT OBJECT myobj)
The "myobject" variable will still be there, but will be useless cause its pointer was destroyed.
 
When you "nil out a variable" you are killing the value in that variable. (Setting it to zero if you will.) Therefore destroying the variable.

Here is a short demonstration:
Code: [Select]
(defun test ()
  (setq myobj (vlax-Ename->Vla-Object (car (entsel))))
  (if (vlax-release-object myobj)
    (prompt "\nI have released the object \n")
    (prompt "\n I couldnt release the object \n")
    )
  (prompt "\nLet's see if the \"myobj\" variable still exists...\n")
  (if myobj
    (prompt "\nYes it does!")
    (prompt "\nNo it dosent!")
    )
  (princ)
  )


Did that help make sence out of it?
Title: (vlax-release-object obj) vs (setq obj nil)
Post by: sinc on August 02, 2004, 04:24:50 PM
Well, it doesn't really answer my question.  Is it necessary to call vlax-release-object, or does that happen automatically when a variable is set to nil or redefined?

For example, I have a loop that creates a bunch of points with the Add method on the CogoPoints collection, one per iteration of the loop.  As each point is created, it is assigned to the variable pnt.  Do I need to (vlax-release-object pnt) at the end of the loop, or is it implicit when the next point is assigned to pnt on the next iteration?  Or do I end up with a bunch of unreferenced vla-objects laying around?  Or is it one of those cases where it only matters if you create a lot of points, because the unreferenced vla-objects get garbage-collected at the end of the routine?

I can add the vlax-release-object to be safe, but I was hoping someone knew exactly what was going on...
Title: (vlax-release-object obj) vs (setq obj nil)
Post by: JohnK on August 02, 2004, 04:48:33 PM
*Sigh*  

Answer: Release at the end of your loop.
Title: (vlax-release-object obj) vs (setq obj nil)
Post by: Mark on August 02, 2004, 05:00:34 PM
Quote from: sinc
I was hoping someone knew exactly what was going on...

I have read many posts on this subject and it would seem the only authority on the subject (Adesk) ain't talkin. I use this rule, it you modifiy it or make it then release it. But that's just my take on it.
Title: (vlax-release-object obj) vs (setq obj nil)
Post by: JohnK on August 02, 2004, 05:11:03 PM
Here's my new take on the subject.

Treat it like a pointer in C++; If you create an object, destroy it. (Would it hurt to destroy it? Nope!)
Title: (vlax-release-object obj) vs (setq obj nil)
Post by: SMadsen on August 02, 2004, 05:30:13 PM
Quote from: Mark Thomas
I have read many posts on this subject and it would seem the only authority on the subject (Adesk) ain't talkin.

Sadly so. Sure, it's only a macro language but still, something like this should have been documented.
Until it is documented (probably never will be), I will always release objects that may be linked to any outside ActiveX server (whenever I remember to, that is). As for native objects I choose to believe that they are swept up by the normal garbage collection (but that's still just a belief).
Title: (vlax-release-object obj) vs (setq obj nil)
Post by: Kerry on August 02, 2004, 06:10:46 PM
Jeff and Stig are correct [ again ]

To clarify a misconception ; A quote from Tony T.
Quote

Calling (vlax-release-object) on a COM object does not destroy it,
it only decrements the COM object's reference count. The COM object
is destroyed only when its reference count reaches 0.
Since each call to (vlax-get-acad-object) increments the reference
count of the Application object, the only way to destroy it is to
call (vlax-release-object) the exact same number of times that
(vlax-get-acad-object) was called:
Command: (setq a (vlax-get-acad-object))
#<VLA-OBJECT IAcadApplication 00ac9920>

Command: (vlax-release-object a)
13

Command: (repeat 10 (vlax-get-acad-object))
#<VLA-OBJECT IAcadApplication 00ac9920>

Command: (vlax-release-object a)
22

Note the result of (vlax-release-object). This value is the COM
object's reference count. Only when (vlax-release-object) returns
0 is the object actually "released", and at that point, any and
all references to it are automatically cleared.


or run through this a line at a time, and watch the return values:

Code: [Select]

(gc) (gc) (gc)
(Setq oLayers (vla-get-layers kbsg:activedoc))
(Setq LayersCollection  (vla-get-layers kbsg:activedoc))
(Setq AllLayers (vla-get-layers kbsg:activedoc))
(Setq ColLayers (vla-get-layers kbsg:activedoc))

(vlax-release-object oLayers)
(vlax-release-object LayersCollection)
(vlax-release-object AllLayers)
(vlax-release-object ColLayers)

(gc) (gc) (gc)


This is one of the reasons I use this construct for global object variables, and simply ensure that local object variables are included in the local defun list. :
Code: [Select]

(or kbsg:acadapp (setq kbsg:acadapp (vlax-get-acad-object)))
(or kbsg:activedoc (setq kbsg:activedoc (vla-get-activedocument kbsg:acadapp)))
(or kbsg:modelspace (setq kbsg:modelspace (vla-get-modelspace kbsg:activedoc)))
Title: (vlax-release-object obj) vs (setq obj nil)
Post by: Kerry on August 02, 2004, 06:24:13 PM
Just to clarify that :

If you have 2 or more variables referencing the same COM object, which invariably happens with the way most people reference the acad-object, activedocument, etc ; applying (vlax-release-object ...  to one of the variables releases that instance count only not all counts.

This can be demonstrated by running my code one line at a time any noting the integer value returned from (vlax-release-object whateverObject)

#<VLA-OBJECT IAcadLayers 00f27ae4>
#<VLA-OBJECT IAcadLayers 00f27ae4>
#<VLA-OBJECT IAcadLayers 00f27ae4>
#<VLA-OBJECT IAcadLayers 00f27ae4>
4
3
2
1

Note that all variables refer to the same object and the decrementing count as the objects [variables] are released.
Title: (vlax-release-object obj) vs (setq obj nil)
Post by: JohnK on August 02, 2004, 08:12:39 PM
First of all No-one can be "correct" on this because "no-one really knows 'cept autodesk!" (And no matter how much respect i have for tony's abilities) i dont concider him to be the end-all-be-all!

I think they are handled by the autocad gabage collector as well but my point is. Creating an object alocates memory. You can create as many instances as you want but your chewing up the stack. Whats the harm in deleting them? There isnt any.

OBTW, If you think about it, my theory about pointers is feasible. that number looks alot like an address to me.  An array.
Title: (vlax-release-object obj) vs (setq obj nil)
Post by: Kerry on August 02, 2004, 09:28:47 PM
I will qualify that then Seven.
My testing and experience agrees with the answer provided by Jeff and Stig.

I would suggest that anyone who wants the answer to this do their own investigation and determine the actual situation for themselves, rather than guessing, or taking anyone elses word for it.

The issue is not what is feasable, it is what is actually correct.
Title: (vlax-release-object obj) vs (setq obj nil)
Post by: JohnK on August 02, 2004, 10:43:14 PM
So then why do you dispute me? Are you saying that i havent done my own testing? I have. I have read that post by Tony, i have read what Reni and Vali. have said about the subject. Ive read what Autodesk has to say about it, Ive built  dozens of procedures to test diff aspects of objects.  

I have not said anything diff in any of my posts about them that wouldnt or couldnt be concidered as wrong. The only thing ive said is that Objects chew up memory and they should be destroyed whenever possible. --If they are to remain Global then make them Global. (Prefix them or supply some sort of identifier to that variable to tell us it is global.) Do not alocate memory for a variable and expect it to be assumed by others that, that variable is and will be "cleaned up by AutoCAD". Do not create a variable and leave a pointer laying about.

***

...Alright, i took a small walk and calmed down. The reason i get so worked up about this is beacuse if we are here to teach others to "program" then we should pass on the good/proper habits we have picked up from others "above" us. If i read, wanting to learn to program, and all of the information i read tells me to destroy what i created (leave the enviroment the way i found it) then how can i justify leaving chunks of un usable memory alocated in the stack. Memory that other AutoCAD process' cant access and use? Like it has been agreeed upon, the documentation isnt there and we dont know if the G.C. cleans up that memory so why risk it?
Title: (vlax-release-object obj) vs (setq obj nil)
Post by: sinc on August 03, 2004, 01:51:09 AM
OK, I've done some exploration (I'm not a big fan of waiting for answers from Autodesk if I don't have to :lol: ), and I think I've figured it out.

The vla-object is an interface object that links the Lisp environment with the Autocad object model.  You create or get vla-objects and assign them to AutoLisp variables; this allows you to interact with the Autocad object.  So, in VLisp, there can be THREE items involved in any entity interaction: the entity itself, the interface object (vla-object), and the AutoLisp variable.  All of these can be created/destroyed independently of the others.

Autolisp variables remain until they are set to nil, which happens automatically on function termination if the variable is local to that function.  VLA-OBJECTs remain until they are vla-released or until they are garbage collected.  All vla-objects that are orphaned - i.e., vla-objects that are not vla-released before their associated Autolisp variable is set to some other value (or nil) - are garbage collected.  Witness:

Code: [Select]
Command: (setq x (vlax-get-acad-object))
#<VLA-OBJECT IAcadApplication 00af9594>

Command: (vlax-release-object x)
4

Command: (setq x (vlax-get-acad-object))
#<VLA-OBJECT IAcadApplication 00af9594>

Command: (setq y (vlax-get-acad-object))
#<VLA-OBJECT IAcadApplication 00af9594>

Command: (vlax-release-object x)
5

Command: (repeat 100 (setq x (vlax-get-acad-object)))
#<VLA-OBJECT IAcadApplication 00af9594>

Command: (vlax-release-object x)
104

Command: (gc)
nil

Command: (vlax-release-object y)
4

Therefore, it is not necessary to call vlax-release-object unless you trigger too many garbage collections.  For example, in a routine such as the following, there's actually a string of vla-objects created and not released:

Code: [Select]
(defun sample:getCurrentTextStyleName ()
  (vla-get-name
    (vla-get-activeTextStyle
      (vla-get-activeDocument
        (vlax-get-acad-object)
      ) ;_ vla-get-activeDocument
    ) ;_ vla-get-activeTextStyle
  ) ;_ vla-get-name
) ;_ defun

However, it's no big deal.  They'll be garbage-collected at the next gc, which happens automatically whenever it becomes necessary.

So, my take on things is that the vla-release-object is generally unnecessary, unless it causes a noticeable impact on performance, and doing explicit releases changes that.

I know that, from a purist point of view, it may be preferable to always use an explicit release, but I would argue that it is frequently better to limit code to functional pieces, rather than adding unnecessary pieces that may be technically more "correct".  Limiting your code to "just the important parts", to whatever extents allowed by the language, is something I usually view as a good thing.  Not only is it faster to write, it results in more-readable code.   It's much easier to look at a function and say "Ah, that does that" if you don't have to trace through a lot of code added merely to satisfy implementation details of the language.

Garbage collection may be "slop" on some level, but if there's no reason to deal with mundane details such as memory management, then I say don't.  Why waste time on code unless it serves a purpose?  Strict memory-management can cause horrendous debugging headaches, as anyone struggling to learn C/C++ data structures can attest.

And, from a software-development point-of-view, it's actually perfectly OK (even desireable) to write the code "sloppy" to get it working, and get the problem-solving logic correct, then go back later and add details such as memory-management to improve performance if it proves necessary or desirable...  Garbage-collection is kind of nice that way.

(Note - this does NOT imply that it's OK to forget to set your non-local AutoLisp variables to nil...)
Title: (vlax-release-object obj) vs (setq obj nil)
Post by: Kerry on August 03, 2004, 03:20:31 AM
sinc ;

The comments from your post are essentially my understanding of the situation.

I have dragged out some old test code which may demonstrate that the memory usage after creating 1,000,000 unreleased global references is considerably different to creating 1,000,000 unreleased local references.
If local unreleased {by user code } references were retained and not automatically released the memory usage for test 101 and 103 would be similar.

I understand that this test is not the most scientific ever produced , but the results are sufficient for me to form an opinion.

I will continue to declare Autocad based objects as locals and not release or nil them. Objects created from any external ActiveX Server will be released and nilled as I am currently doing.

This is not intended as a pissing contest.
Perhaps someone has test results that can better define any differences. I would be interested in seeing them, particularly if the results show me how to improve my code.
Regards.Kerry
Code: [Select]

(vl-load-com)
(defun c:test101 (/ oLine StartPoint EndPoint cnt)
   (gc)
   (or gx:acadapp (setq gx:acadapp (vlax-get-acad-object)))
   (or gx:activedoc (setq gx:activedoc (vla-get-activedocument gx:acadapp)))
   (or gx:modelspace (setq gx:modelspace (vla-get-modelspace gx:activedoc)))
   ;;
   ;;
   (setq StartPoint '(0 0 0)
         EndPoint   '(100 100 100)
         cnt        0
   )
   (vla-put-color (setq oLine (vla-addline gx:modelspace
                                           (vlax-3d-point StartPoint)
                                           (vlax-3d-point EndPoint)
                              )
                  )
                  cnt
   )
   (vl-cmdf "status")
   (mem)
   (prompt "\n Be prepared to wait a while ...... ")
   (repeat 500000 (setq cnt (1+ cnt)) (test101 (rem cnt 255)))          
   (vl-cmdf "status")
   (mem)
   (princ)
)
(defun test101 (newcolor / oLine tmp)
   (vla-put-color (setq oLine (vlax-ename->vla-object (entlast))) newcolor)
   (setq tmp (vla-get-layers gx:activedoc))
   (princ)
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun c:test102 (/ oLine StartPoint EndPoint cnt)
   (gc)
   (or gx:acadapp (setq gx:acadapp (vlax-get-acad-object)))
   (or gx:activedoc (setq gx:activedoc (vla-get-activedocument gx:acadapp)))
   (or gx:modelspace (setq gx:modelspace (vla-get-modelspace gx:activedoc)))
   ;;
   ;;
   (setq StartPoint '(0 0 0)
         EndPoint   '(100 100 100)
         cnt        0
   )
   (vla-put-color (setq oLine (vla-addline gx:modelspace
                                           (vlax-3d-point StartPoint)
                                           (vlax-3d-point EndPoint)
                              )
                  )
                  cnt
   )
   (vl-cmdf "status")
   (mem)
   (prompt "\n Be prepared to wait a while ...... ")
   (repeat 500000 (setq cnt (1+ cnt)) (test102 (rem cnt 255)))          
   (vl-cmdf "status")
   (mem)
   (princ)
)
(defun test102 (newcolor / oLine tmp)
   (vla-put-color (setq oLine (vlax-ename->vla-object (entlast))) newcolor)
   (setq tmp (vla-get-layers gx:activedoc))
   (vlax-release-object oLine)
   (vlax-release-object tmp)
   (princ)
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun c:test103 (/ oLine StartPoint EndPoint cnt)
   (gc)
   (or gx:acadapp (setq gx:acadapp (vlax-get-acad-object)))
   (or gx:activedoc (setq gx:activedoc (vla-get-activedocument gx:acadapp)))
   (or gx:modelspace (setq gx:modelspace (vla-get-modelspace gx:activedoc)))
   ;;
   ;;
   (setq StartPoint '(0 0 0)
         EndPoint   '(100 100 100)
         cnt        0
   )
   (vla-put-color (setq oLine (vla-addline gx:modelspace
                                           (vlax-3d-point StartPoint)
                                           (vlax-3d-point EndPoint)
                              )
                  )
                  cnt
   )
   (vl-cmdf "status")
   (mem)
   (prompt "\n Be prepared to wait a while ...... ")
   (repeat 500000 (setq cnt (1+ cnt)) (test103 cnt))
   (vl-cmdf "status")
   (mem)
   (princ)
)


(defun test103 (cnt /)
   (vla-put-color (set (read (strcat "oLine-" (itoa cnt))) (vlax-ename->vla-object (entlast)))
                  (rem cnt 255)
   )
   (set (read (strcat "oLayerCollection-" (itoa cnt)))
        (vla-get-layers gx:activedoc)
   )
   (princ)
)
(princ)


The test results : be prepared to wait .. restart Autocad between tests ..
Code: [Select]

Command: (load "memtest")
Command: test101
status 47 objects in Drawing1.dwg
Free dwg disk (D:) space: 1321.5 MBytes
Free temp disk (D:) space: 1321.5 MBytes
Free physical memory: 238.8 Mbytes (out of 511.5M).
Free swap file space: 3275.9 Mbytes (out of 3551.9M).

Command: ; GC calls: 23; GC run time: 373 ms
Dynamic memory segments statistic:
PgSz  Used  Free  FMCL  Segs  Type
 512    13   368   115     3  lisp stacks
 256  2393   621   104    10  bytecode area
4096   281     4     4    19  CONS memory
  32   844  1139  1093     1  ::new
4096    59   136    14    13  DM Str
4096   321     9     7    22  DMxx memory
 128     3   508   508     1  bstack body
Segment size: 65536, total used: 69, free: 3

 Be prepared to wait a while ......
 status 47 objects in Drawing1.dwg
Free dwg disk (D:) space: 1305.7 MBytes
Free temp disk (D:) space: 1305.7 MBytes
Free physical memory: 181.3 Mbytes (out of 511.5M).
Free swap file space: 3219.3 Mbytes (out of 3551.9M).

Command: ; GC calls: 493; GC run time: 15443 ms
Dynamic memory segments statistic:
PgSz  Used  Free  FMCL  Segs  Type
 512    13   368   115     3  lisp stacks
 256  2393   621   104    10  bytecode area
4096   281     4     4    19  CONS memory
  32   844  1139  1093     1  ::new
4096    59   136    14    13  DM Str
4096   338     7     5    23  DMxx memory
 128     3   508   508     1  bstack body
Segment size: 65536, total used: 70, free: 2

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Command: (load "memtest")

Command: test102
status 47 objects in Drawing1.dwg
Free dwg disk (D:) space: 1306.0 MBytes
Free temp disk (D:) space: 1306.0 MBytes
Free physical memory: 240.7 Mbytes (out of 511.5M).
Free swap file space: 3281.3 Mbytes (out of 3551.9M).

Command: ; GC calls: 23; GC run time: 343 ms
Dynamic memory segments statistic:
PgSz  Used  Free  FMCL  Segs  Type
 512    13   368   115     3  lisp stacks
 256  2393   621   104    10  bytecode area
4096   281     4     4    19  CONS memory
  32   844  1139  1093     1  ::new
4096    59   136    14    13  DM Str
4096   321     9     7    22  DMxx memory
 128     3   508   508     1  bstack body
Segment size: 65536, total used: 69, free: 3

 Be prepared to wait a while ......
 status 47 objects in Drawing1.dwg
Free dwg disk (D:) space: 1290.2 MBytes
Free temp disk (D:) space: 1290.2 MBytes
Free physical memory: 183.3 Mbytes (out of 511.5M).
Free swap file space: 3225.1 Mbytes (out of 3551.9M).

Command: ; GC calls: 493; GC run time: 15570 ms
Dynamic memory segments statistic:
PgSz  Used  Free  FMCL  Segs  Type
 512    13   368   115     3  lisp stacks
 256  2393   621   104    10  bytecode area
4096   281     4     4    19  CONS memory
  32   844  1139  1093     1  ::new
4096    59   136    14    13  DM Str
4096   338     7     5    23  DMxx memory
 128     3   508   508     1  bstack body
Segment size: 65536, total used: 70, free: 2

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Command: (load "memtest")

Command: test103
status 47 objects in Drawing1.dwg
Free dwg disk (D:) space: 1290.4 MBytes
Free temp disk (D:) space: 1290.4 MBytes
Free physical memory: 239.2 Mbytes (out of 511.5M).
Free swap file space: 3281.0 Mbytes (out of 3551.9M).

Command: ; GC calls: 23; GC run time: 344 ms
Dynamic memory segments statistic:
PgSz  Used  Free  FMCL  Segs  Type
 512    13   368   115     3  lisp stacks
 256  2396   618   104    10  bytecode area
4096   281     4     4    19  CONS memory
  32   844  1139  1093     1  ::new
4096    59   136    14    13  DM Str
4096   321     9     7    22  DMxx memory
 128     3   508   508     1  bstack body
Segment size: 65536, total used: 69, free: 3

 Be prepared to wait a while ......
 status 47 objects in Drawing1.dwg
Free dwg disk (D:) space: 1274.7 MBytes
Free temp disk (D:) space: 1274.7 MBytes
Free physical memory: 55.2 Mbytes (out of 511.5M).
Free swap file space: 3070.9 Mbytes (out of 3551.9M).


Command: ; GC calls: 124; GC run time: 57013 ms
Dynamic memory segments statistic:
PgSz  Used  Free  FMCL  Segs  Type
 512    13   368   115     3  lisp stacks
 256  2396   618   104    10  bytecode area
4096  5894     1     1   393  CONS memory
  32   850  1133  1087     1  ::new
4096  6932    13    13   463  DM Str
4096 21777   411     8  1479  DMxx memory
 128     3   508   508     1  bstack body
Segment size: 65536, total used: 2350, free: 0
Title: (vlax-release-object obj) vs (setq obj nil)
Post by: daron on August 03, 2004, 08:53:06 AM
Sorry Kerry, I can't show anything or help improve your code. All I can do is share what I can recollect of an experience I had in not releasing my objects. When I learned ActiveX, not too long ago, I was taught to always release my objects. As I progressed and found myself writing more code using AX, I became lazy, too busy or both. I developed a routine that would take a selected group of objects, move them near the 0,0 area and wblock them out according to the number of a piece of text within the selection. This would repeat as often times as there were objects with this type of text in the selection. There were a few more steps to the function, like adding a title-block with all possible information and printing the area out. At first, I left out the releasing portion of the code. It worked for a short time. In a project where I had 100 groups of objects to process, I found the memory of my computer quickly eaten up. 100 property lots (groups of objects) was small scale, so I knew I needed to do something. I got over my laziness, set up the necessary vlax-release-objects and began again on a fresh day. The start of the job didn't increase nor decrease in speed, but I was able to finish the job and each one after, without the type of slow down I had experienced previously.

Don't do it anymore. Can't test it anymore, but I would concur with se7en, release your objects. It certainly doesn't hurt. At the same time, I believe there are some procedures out there that have been written that you can download to not have to write it out each time, but just use them.
Title: (vlax-release-object obj) vs (setq obj nil)
Post by: Kerry on August 03, 2004, 09:36:24 AM
Daron ,
Were these global variables holding the objects or local ?

I would have to see the code to pass comment.
Title: (vlax-release-object obj) vs (setq obj nil)
Post by: SMadsen on August 03, 2004, 12:30:34 PM
What bugs me most about the missing documentation is that I have no idea if unreleased objects causes bad things such as memory leaks and slowed performance. It's very common to nest calls through multiple objects without a chance of decrementing the reference count.

Does a call like (vla-get-name (vla-item (vla-get-documents (vlax-get-acad-object)) myIndex)) sound familiar? It increments the reference count of both the Documents collection and the application object but there's no chance to release the references. Try this little test:

Command: (vlax-release-object (vlax-get-acad-object))
3

Command: (vlax-release-object (vla-get-documents (vlax-get-acad-object)))
1

Command: (vla-get-name (vla-item (vla-get-documents (vlax-get-acad-object)) 0))
"Drawing2.dwg"

Command: (vlax-release-object (vla-get-documents (vlax-get-acad-object)))
2

Command: (vlax-release-object (vlax-get-acad-object))
7

Repetition of the last two calls will never return smaller counters than the above, which means that there are references that can not be released.

Now, the document collection and the application will always be referenced so it doesn't matter that they can't be cleaned up but if you go further down the hierarchy than you may lock objects that otherwise were up for garbage collection (and global/local referencing is indifferent to this).
As mentioned previously, with in-process objects it may not be a problem at all but just to know that there may be a problem and that it's not documented .. well, that sucks.
Title: (vlax-release-object obj) vs (setq obj nil)
Post by: daron on August 03, 2004, 01:15:15 PM
I believe they were local, Kerry.
Title: (vlax-release-object obj) vs (setq obj nil)
Post by: sinc on August 05, 2004, 04:21:01 PM
Quote from: SMadsen
Now, the document collection and the application will always be referenced so it doesn't matter that they can't be cleaned up but if you go further down the hierarchy than you may lock objects that otherwise were up for garbage collection (and global/local referencing is indifferent to this).
As mentioned previously, with in-process objects it may not be a problem at all but just to know that there may be a problem and that it's not documented .. well, that sucks.

I have confirmed that there is a definite bug in here.  Normal objects seem fine, but distributed objects (ActiveX) are definitely buggy.

At this point, I'm not familiar enough with ActiveX to be sure if the problem is an ActiveX problem, or a problem in Autodesk's VLisp/VBA bridge, or something else.  Right now, I suspect the VLisp/VBA bridge, since not releasing the acad object doesn't cause a problem.  The vlax-get-acadObject method is probably hard-coded in a way that bypasses the general bridging mechanism, thereby bypassing the bug.

I'll let you know if I figure out anything else useful, but to be safe, I guess the only thing to do is to vla-release all vla-objects.  This is annoying, like Stig says, since not only does it mean you have to include a lot of otherwise unnecessary vla-release-object lines, it also means you can't inline vla- commands; in other words,

<plain english translation>

DON'T use constructs like:
(vla-get-name (vla-item (vla-get-documents (vlax-get-acad-object)) myIndex))

</plain english translation>

Instead, you have to assign the result of each vla- command to a local variable, so you can vla-release it later.  Blech!  :fart:

This is DEFINITELY something that should be in the documentation, in multiple places, underlined, in capital letters, quotated, with circles and arrows...