SetProp() without RemoveProp()..?

Just starting out? Need help? Post your questions and find answers here.
mesozorn
Enthusiast
Enthusiast
Posts: 171
Joined: Fri Feb 20, 2009 2:23 am

SetProp() without RemoveProp()..?

Post by mesozorn »

Over at MSDN it mentions that after using SetProp to assign a property to a window or control, it is necessary to use RemoveProp to de-assign that property prior to closing the window or the App.

http://msdn.microsoft.com/en-us/library ... S.85).aspx

My question is, what will happen if SetProp is used to assign properties, and then the program is closed down completely without bothering to call RemoveProp to remove each and every property that was created? Will there be a memory leak (or any other undesirable consquences) or will the properties get automatically deallocated as the controls and ultimately the window/application is closed?

Such as in the example below, what if the main window is closed and RemoveProp is never called? Is there any definitive, authoritative answer on what the consequences would be? Thanks...!

Code: Select all

If OpenWindow(0, 0, 0, 222, 200, "ButtonGadgets", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    
    ButtonGadget(1, 10, 40, 200, 20, "Left Button", #PB_Button_Left)
    
    SetProp_(GadgetID(1),"prop1",1)
    SetProp_(GadgetID(1),"prop2",2)
    SetProp_(GadgetID(1),"prop3",3)
    SetProp_(GadgetID(1),"prop4",4)
    SetProp_(GadgetID(1),"prop5",5)
    
    Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
mesozorn
Enthusiast
Enthusiast
Posts: 171
Joined: Fri Feb 20, 2009 2:23 am

Re: SetProp() without RemoveProp()..?

Post by mesozorn »

Anyone...anyone... Bueller?
Edwin Knoppert
Addict
Addict
Posts: 1073
Joined: Fri Apr 25, 2003 11:13 pm
Location: Netherlands
Contact:

Re: SetProp() without RemoveProp()..?

Post by Edwin Knoppert »

It only increases the stupidity level..
Many things in 32bit (not 16 :) ) are subject to be terminated properly on shutdown but should not be you joker card here.
Once you go this route, you'll only find yourself in the future.

Iow, you should not even ask :)
mesozorn
Enthusiast
Enthusiast
Posts: 171
Joined: Fri Feb 20, 2009 2:23 am

Re: SetProp() without RemoveProp()..?

Post by mesozorn »

Thanks for your reply, although I'm not sure I completely understand it...

While I infer that you're advising against it, is that just a general opinion or do you know for certain what will occur if RemoveProp() is not used? I certainly never use the native PB FreeGadget() on any of the hundreds of gadgets created before ending a program, going with the assumption that all gadgets and associated data will be automatically deallocated upon shutdown. Is Windows itself really not capable of dissolving such associated control properties once the control itself is found to no longer exist?
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Re: SetProp() without RemoveProp()..?

Post by netmaestro »

do you know for certain what will occur if RemoveProp() is not used?
MSDN is clear on this point - you will create a leak if you don't remove the properties yourself. If you set a property, remove it.
BERESHEIT
Edwin Knoppert
Addict
Addict
Posts: 1073
Joined: Fri Apr 25, 2003 11:13 pm
Location: Netherlands
Contact:

Re: SetProp() without RemoveProp()..?

Post by Edwin Knoppert »

If MSDN tells you that you should destroy things or remove them it is not ideal to ignore that.
It's not a problem once you closed your app is what i am saying but it is during the life time of the app.
It's poor programming if you discover you get out of memory or gdi issue or whatever because you didn't like to clean up.

If you do.., do you want your customers to restart your app each several hours due some flaws you made?
Edwin Knoppert
Addict
Addict
Posts: 1073
Joined: Fri Apr 25, 2003 11:13 pm
Location: Netherlands
Contact:

Re: SetProp() without RemoveProp()..?

Post by Edwin Knoppert »

>Is Windows itself really not capable of dissolving such associated control properties once the control itself is found to no longer exist?
For most things: Not
I can't even think of a situation this actually happens.

In VB/PB it may be done for you, in ordinary Windows it's create and destroy 'manually'.
mesozorn
Enthusiast
Enthusiast
Posts: 171
Joined: Fri Feb 20, 2009 2:23 am

Re: SetProp() without RemoveProp()..?

Post by mesozorn »

netmaestro wrote:
do you know for certain what will occur if RemoveProp() is not used?
MSDN is clear on this point - you will create a leak if you don't remove the properties yourself. If you set a property, remove it.
Thanks.. out of curiosity where exactly is MSDN clear on that point? Are you referring to this text:
Before a window is destroyed (that is, before it returns from processing the WM_NCDESTROY message), an application must remove all entries it has added to the property list. The application must use the RemoveProp function to remove the entries.
? To me that is ambiguous as it doesn't specifically mention that a leak will occur, it just says that you "must" do it. It is fair enough to infer a leak, which is what led me to post my question in the first place, but it is not explicit in stating that a leak will occur. (EDIT: See my next reply below, I am only talking about leaks after the app closes completely, not during it's running time.)

The reason I ask this is because I may possibly have hundreds of gadgets, each with dozens of properties, and it seems very laborious to have to remove each and every one of them manually upon shutdown. I can think of ways to easily automate this of course, but they usually necessitate a small time penalty at the time of gadget creation, not just at shutdown. I suppose that is my only option however, if a leak really is the consequence of not removing the property with RemoveProp().
Last edited by mesozorn on Tue May 04, 2010 9:45 pm, edited 1 time in total.
mesozorn
Enthusiast
Enthusiast
Posts: 171
Joined: Fri Feb 20, 2009 2:23 am

Re: SetProp() without RemoveProp()..?

Post by mesozorn »

Edwin Knoppert wrote:It's not a problem once you closed your app is what i am saying but it is during the life time of the app.
Hmm, actually it happens to be the case that I am only concerned about leaks after my app has been closed, not during its running lifetime. I am never destroying controls during the app's running time and wanting the property memory deallocated instantly at that moment (though that would still be nice/logical). I'm fine with all controls and properties contintuing to exist right up until the point that the entire app is closed, but after that point I'd want to be sure that the allocated memory for the properties isn't STILL marked as occupied in the operating system. So that if a user opened and closed my app thousands of times, available memory would slowly decrease each time indefinitely - that's what I want to avoid.

I have a finite number of controls in my app and they are not constantly being created/destroyed over and over again in one session, so leaks from SetProp() during a single running session aren't an issue. It's after the app is closed that I'm concerned with.

Does that change anything?
Edwin Knoppert
Addict
Addict
Posts: 1073
Joined: Fri Apr 25, 2003 11:13 pm
Location: Netherlands
Contact:

Re: SetProp() without RemoveProp()..?

Post by Edwin Knoppert »

Not from my point of view.
freak
PureBasic Team
PureBasic Team
Posts: 5944
Joined: Fri Apr 25, 2003 5:21 pm
Location: Germany

Re: SetProp() without RemoveProp()..?

Post by freak »

Yes, there is a leak. It will leak the global atom with the property name.

The reason is that you can manage properties either by atom (see GlobalAddAtom), or by string (in which case SetProp converts it to an atom for you). Internally all properties are managed by atom. Windows cannot just call GlobalDeleteAtom on all properties when the window closes because it does not know wether you created the atom and passed it directly or wether SetProp created it because you passed a string. Since atoms live past the lifetime of your process if you do not delete them, these will leak.

The point is moot though. If the docs say you have to clean it up then just do it.
quidquid Latine dictum sit altum videtur
mesozorn
Enthusiast
Enthusiast
Posts: 171
Joined: Fri Feb 20, 2009 2:23 am

Re: SetProp() without RemoveProp()..?

Post by mesozorn »

Okay, thanks again for the helpful replies. It seems a shame that one can't just call SetProp_() all over the place willy-nilly the same way as SetGadgetData(), without having to worry about undoing everything before closing. It's certainly much more convenient not having to call RemoveGadgetData() on hundreds of gadgets before ending an app.

In any case the only ways I've managed to handle adding unlimited properties to gadgets/controls on the fly, without having to manually remove each one individually is as follows. If someone has a better, more efficient way of easily storing/associating data/properties along with controls I'd definitely be much obliged to know about it..

1) Using a linked list along with SetProp_() to track all added properties:

Code: Select all

  Structure Prop
    handle.l
    Property.s
    Value.l
  EndStructure  
  
  Global NewList Properties.Prop()
    
  Macro SetProp(hWnd,prop,val)
  
    SetProp_(hWnd,prop,val)
    found=0
    ForEach Properties()
      If Properties()\handle=hWnd And Properties()\property=prop
        Properties()\value=val:found=1:Break
      EndIf
    Next
    
    If Not found
      AddElement(Properties())
      Properties()\handle=hWnd
      Properties()\property=prop
      Properties()\value=val
    EndIf

  EndMacro


If OpenWindow(0, 0, 0, 270, 160, "TextGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    
  TextGadget(1, 10,  70, 250, 20, "SetProp Test", #PB_Text_Center)
  
  SetProp(GadgetID(1),"Property1",1)  
  SetProp(GadgetID(1),"Property2",2)  
  SetProp(GadgetID(1),"Property3",3)  
  SetProp(GadgetID(1),"Property4",4)  
  SetProp(GadgetID(1),"Property5",5)  
    
  Debug GetProp_(GadgetID(1),"Property1")  
  Debug GetProp_(GadgetID(1),"Property2")
  Debug GetProp_(GadgetID(1),"Property3")
  Debug GetProp_(GadgetID(1),"Property4")
  Debug GetProp_(GadgetID(1),"Property5")
    
  Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
  
  ForEach Properties()
   RemoveProp_(Properties()\handle,Properties()\property)
  Next
  
EndIf

2) Using only the linked list itself instead of API calls, for the same effect:

Code: Select all

  Structure Prop
    gadget.l
    Property.s
    Value.l
  EndStructure  
  
  Global NewList Properties.Prop()
    
  Procedure SetProp(gadgetnum,prop.s,val)
  
    found=0
    ForEach Properties()
      If Properties()\gadget=gadgetnum And Properties()\property=prop
        Properties()\value=val:found=1:Break
      EndIf
    Next
    
    If Not found
      AddElement(Properties())
      Properties()\gadget=gadgetnum
      Properties()\property=prop
      Properties()\value=val
    EndIf

  EndProcedure
  
  Procedure GetProp(gadgetnum,prop.s)
  
    ForEach Properties()
      If Properties()\gadget=gadgetnum And Properties()\property=prop
        ProcedureReturn Properties()\value
      EndIf
    Next
    ProcedureReturn 0

  EndProcedure

If OpenWindow(0, 0, 0, 270, 160, "TextGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
 
  TextGadget(1, 10,  70, 250, 20, "SetProp Test", #PB_Text_Center)
  
  SetProp(1,"Property1",1)  
  SetProp(1,"Property2",2)  
  SetProp(1,"Property3",3)  
  SetProp(1,"Property4",4)  
  SetProp(1,"Property5",5)  
    
  Debug GetProp(1,"Property1")  
  Debug GetProp(1,"Property2")
  Debug GetProp(1,"Property3")
  Debug GetProp(1,"Property4")
  Debug GetProp(1,"Property5")
    
  Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
   
  
EndIf
Both of these work, but are not as speed-efficient as the API SetProp_() and GetProp_() versions by themselves. I know about EnumProps_() as well, but am not sure whether it would be the ideal way of automatically removing added properties.

Any suggestions are welcome, thanks...

.
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Re: SetProp() without RemoveProp()..?

Post by srod »

If dealing with a potentially unbounded and unknown number of properties attached to a window then I will use EnumPropsEx_() to delete them. You really do not need to store them all in a list.

EnumPropsEx_() allows you to loop through all of the properties from where you can simply delete them etc. I do this with EasyVENT and it works fine.
I may look like a mule, but I'm not a complete ass.
breeze4me
Enthusiast
Enthusiast
Posts: 633
Joined: Thu Mar 09, 2006 9:24 am
Location: S. Kor

Re: SetProp() without RemoveProp()..?

Post by breeze4me »

try this way.

Code: Select all

Procedure PropEnumProc(hwnd, *lpszString, hData)
  Protected PropStr.s
  If *lpszString >> 16  ;if *lpszString is a real string pointer
    PropStr = PeekS(*lpszString)
    If PropStr <> "PB_ID" ;if not a PB internal prop.
      Debug PropStr
      RemoveProp_(hwnd, PropStr)
    EndIf
  EndIf
  ProcedureReturn #True
EndProcedure

Procedure RemoveProps(gadget)
  If IsGadget(gadget)
    EnumProps_(GadgetID(gadget), @PropEnumProc())
  EndIf
EndProcedure

If OpenWindow(0, 0, 0, 270, 160, "TextGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

  hwnd = TextGadget(1, 10,  70, 250, 20, "SetProp Test", #PB_Text_Center)
  
  SetProp_(hwnd,"Property1",1)
  SetProp_(hwnd,"Property2",2)
  SetProp_(hwnd,"Property3",3)
  SetProp_(hwnd,"Property4",4)
  SetProp_(hwnd,"Property5",5)
    
    
  Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
  
  Debug GetProp_(hwnd,"Property1")
  Debug GetProp_(hwnd,"Property2")
  Debug GetProp_(hwnd,"Property3")
  Debug GetProp_(hwnd,"Property4")
  Debug GetProp_(hwnd,"Property5")
  
  RemoveProps(1)
  
  Debug "all props removed !"
  Debug GetProp_(hwnd,"Property1")
  Debug GetProp_(hwnd,"Property2")
  Debug GetProp_(hwnd,"Property3")
  Debug GetProp_(hwnd,"Property4")
  Debug GetProp_(hwnd,"Property5")
  
EndIf
mesozorn
Enthusiast
Enthusiast
Posts: 171
Joined: Fri Feb 20, 2009 2:23 am

Re: SetProp() without RemoveProp()..?

Post by mesozorn »

Thanks, I had just been working through creating a smiliar routine myself before checking back here, and almost had it working but for one key thing. Below is my version for automatically removing all properties from all controls upon app close. The one thing which kept tripping me up was the absence of the line:

If *lpszString >> 16 ;if *lpszString is a real string pointer

I am not currently familiar with the operator ">> 16". What exactly does it mean? And, why do we need to check whether that pointer is a real string pointer? Wouldn't it always be, if EnumProps_() is always only calling the procedure when it finds a property attached to a control? Under what circumstance will EnumProps() call the EnumChildProc() but NOT have *lpszString be a real string pointer? This I don't currently understand. (EDIT: I am guessing this has something to do with 16-bit integer "atoms", with which I am also unfamiliar.)

Also, I presume it is safe to omit the line:

If PropStr <> "PB_ID" ;if not a PB internal prop.

If this is all being done upon app close, and it no longer matters whether internal PB props are haphazardly removed...?

Code: Select all

Procedure RemoveAllProps(hwnd,*lpszString,hData)
  If *lpszString >> 16
    If RemoveProp_(hwnd,PeekS(*lpszstring)):
      Debug "Removed "+PeekS(*lpszstring)
    EndIf
  EndIf
  ProcedureReturn 1
EndProcedure

Procedure EnumChildProc(hwnd,lParam)
  EnumProps_(hWnd, @RemoveAllProps())
  ProcedureReturn 1
EndProcedure


If OpenWindow(0, 0, 0, 322, 150, "ContainerGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    ContainerGadget(0, 8, 8, 306, 133, #PB_Container_Raised)
      ButtonGadget(1, 10, 15, 80, 24, "Button 1")
      ButtonGadget(2, 95, 15, 80, 24, "Button 2")
    CloseGadgetList()
    
    SetProp_(GadgetID(1),"CreatedProperty1",12345)
    SetProp_(GadgetID(1),"CreatedProperty2",12345)
    SetProp_(GadgetID(2),"CreatedProperty3",12345)
    SetProp_(GadgetID(2),"CreatedProperty4",12345)
    SetProp_(GadgetID(0),"CreatedProperty5",12345)
    
    Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
    
    EnumChildWindows_(WindowID(0),@enumchildproc(),0)  
    
EndIf
Last edited by mesozorn on Wed May 05, 2010 6:23 pm, edited 1 time in total.
Post Reply