Author Topic: (vlax-release-object obj) vs (setq obj nil)  (Read 17160 times)

0 Members and 1 Guest are viewing this topic.

sinc

  • Guest
(vlax-release-object obj) vs (setq obj nil)
« 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?

Jeff_M

  • King Gator
  • Posts: 4087
  • C3D user & customizer
(vlax-release-object obj) vs (setq obj nil)
« Reply #1 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".

JohnK

  • Administrator
  • Seagull
  • Posts: 10605
(vlax-release-object obj) vs (setq obj nil)
« Reply #2 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.
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

JohnK

  • Administrator
  • Seagull
  • Posts: 10605
(vlax-release-object obj) vs (setq obj nil)
« Reply #3 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?
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

sinc

  • Guest
(vlax-release-object obj) vs (setq obj nil)
« Reply #4 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...

JohnK

  • Administrator
  • Seagull
  • Posts: 10605
(vlax-release-object obj) vs (setq obj nil)
« Reply #5 on: August 02, 2004, 04:48:33 PM »
*Sigh*  

Answer: Release at the end of your loop.
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

Mark

  • Custom Title
  • Seagull
  • Posts: 28753
(vlax-release-object obj) vs (setq obj nil)
« Reply #6 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.
TheSwamp.org  (serving the CAD community since 2003)

JohnK

  • Administrator
  • Seagull
  • Posts: 10605
(vlax-release-object obj) vs (setq obj nil)
« Reply #7 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!)
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

SMadsen

  • Guest
(vlax-release-object obj) vs (setq obj nil)
« Reply #8 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).

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
(vlax-release-object obj) vs (setq obj nil)
« Reply #9 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)))
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
(vlax-release-object obj) vs (setq obj nil)
« Reply #10 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.
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

JohnK

  • Administrator
  • Seagull
  • Posts: 10605
(vlax-release-object obj) vs (setq obj nil)
« Reply #11 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.
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
(vlax-release-object obj) vs (setq obj nil)
« Reply #12 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.
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

JohnK

  • Administrator
  • Seagull
  • Posts: 10605
(vlax-release-object obj) vs (setq obj nil)
« Reply #13 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?
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

sinc

  • Guest
(vlax-release-object obj) vs (setq obj nil)
« Reply #14 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...)