Project Home
Project Home
Trackers
Trackers
Documents
Documents
Wiki
Wiki
Discussion Forums
Discussions
Project Information
Project Info
Forum Topic - Photon Custom Widgets: (21 Items)
   
Photon Custom Widgets  
Hello,

I have inherited several Photon Custom widgets and have a question with regard to freeing resources.

One of the custom widgets inherits from PtLabel and in it's defaults func has code like this: w->label.string = 
calloc(80,1);

How does this memory get freed when the widget is destroyed.  I understood that string resources are freed automatically
 based on strlen() so wouldn't this code introduce a memory leak if the string copied in wasn't exactly 80 bytes in 
length?

Also there are several customs widgets that add their own resources and use strdup() to set initial values.  How does 
this memory get freed?

Thanks for your help.  This is my first exposure to custom widgets :-).

Larry  
Re: Photon Custom Widgets  
Hi Larry,

to my knowledge, ALLOC, STRALLOC, and ARRAY resources are freed automatically by the Photon library when the widget is 
deleted. Any other allocated resources you'll need to free() yourself in the widget class' destruction method 
(Pt_SET_DESTROY_F).

- Thomas
Re: Photon Custom Widgets  
Thanks for the information.  The code w->label.string = calloc(80,1) is setting the string field in the parent class 
label.  According to the Building Custom Widgets documentation (pg 132), this field is of type Pt_ARG_IS_STRING.  On 
page 41 it says that String Resources are allocated based on the value returned by strlen().

So, my question is, if when the widget is being destroyed how does it free this memory that was allocated?  If it does 
it based on the length of the string that is currently in the resource isn't this a potential memory leak.

In fact, if this is a STRING resource, as opposed to an alloc resource is it correct in the first case to be using 
calloc?

Thanks for your help.
Re: Photon Custom Widgets  
Hey Larry,

> On page 41 it says that String Resources are allocated based on the 
> value returned by strlen().

Yes, when using the library's standard resource setting functions. If you are allocating yourself, it's up to you. You 
just need to make sure that the pointer does in fact point to dynamically allocated memory and -if storing a string in 
the allocated chunk- that the allocation will be sufficiently arge enough to hold the string. If you want to allocate 
more than strlen(s)+1, or allocate less and clip the string - feel free.

> So, my question is, if when the widget is being destroyed how does 
> it free this memory that was allocated?  If it does it based on the length 
> of the string that is currently in the resource isn't this a potential memory 
> leak.

No. It uses standard malloc/free mechanisms behind the scenes (just like, e.g., strdup() does.) The heap management will
 know how large each allocated piece is, you do not have to have that knowledge explicitly when free()ing the block.

> In fact, if this is a STRING resource, as opposed to an alloc resource is 
> it correct in the first case to be using calloc?

See above - entirely your choice. Though I'd probably not use calloc, as that will fill the allocated buffer with 0s -- 
which will immediately afterwards be overwritten with your non-0 string content...

- Thomas
Re: Photon Custom Widgets  
Hi Thomas,

Thank you for your reply.  This custom widget building is all new to me so please allow me to ask for further 
clarification.

Are you saying that regardless of resource type it is up to the developer to free memory if they obtain it via the 
Standard C library as opposed to some Photon API?

Larry

Re: Photon Custom Widgets  
Sorry, obviously a misexpression on my side.

No - whether or not you'll need to free() an allocated resource yourself does not depend on who did the allocation, but 
rather on the type of resource / member. String, array, and alloc resources will be freed automatically. If you should 
have other resources, or widget structure members not registered as resources, that are associated with dynamically 
allocated memory, you'll have to do the free().

Or, put in very crude pseudo-code terms:
   DestroyWidget( wgt ) {
      for all resources r of wgt->class do {
         switch ( r->type ) {
         case STRING:
         case ARRAY:
         case ALLOC:
             free( POINTER(wgt,r) );
         }
      }
   }

- Thomas
Re: Photon Custom Widgets  
Hi Thomas,

The string resources we are assigning are being set with straight assignment statements in the widget defaults function.
  We are not using PtSetResources for these initial assignments and we don't have a destructor-cleanup function.  We are
 relying on the default Photon code.

How does the Photon library code know the difference between:

w->label.string = calloc(80,1);

and 

w->label.string = "This is a string";

If it calls free() internally on the static string isn't this a problem?

Thanks.

Larry  
Re: Photon Custom Widgets  
Hi Thomas,

Still trying to understand the process ... any comments to my previous post?

Thanks.

Re: Photon Custom Widgets  
Hey Larry,

sorry, was travelling & not monitoring this week.

To answer your first question,
> How does the Photon library code know the difference between:
>   w->label.string = calloc(80,1);
> and 
>   w->label.string = "This is a string";
...it doesn't. It simply can't, just like any old C program can't - or only could at high costs and/or using some bad 
hacks.

If your string resources are defined as Pt_ARG_IS_STRING and the default destructor method is used, then assigning a 
constant string literal is at least an error - even if it didn't cause a visible /problem/ in your tests yet.

So, to initialize your string resources, please use malloc/calloc+strcpy, or strdup.

Cheers,
- Thomas
Re: Photon Custom Widgets  
Thank you Thomas.  That helps clear things up.  Is there some where in the online documentation that explains this?  
After reading the Widget Building Documentation it wasn't clear to me how the magic worked :-).

Now  back to tracking memory leaks ....

I have a simple application with a window and one custom widget.  A timer on the base window creates and destroys the 
window every 500 msec.

I can watch with sin and see the memory increase slowly over time.  Approximately 7 meg over 60 hours.

Any suggestions for tracking this down?

Thanks.

Larry
Re: Photon Custom Widgets  
Weird ....

If I #ifdef out the code in the widget's default function the leak stops ...

Changing the size of the requested calloc'd memory from 80 to 1024 bytes seemd to have no effect on the size of the leak
 ....

In all cases it seems the memory usage jumps up in 8K chunks.

Defaults function is very simple:

w->date = NULL;
w->time = NULL;
w->label.string = calloc (80,1);

label.string is inherited from the PtLabel widget and we have no destroy function.  Relying on the default destructor ..
.

????
Re: Photon Custom Widgets  
if( w->label.string ) {
   free( w->label.string );
}
w->label.string = calloc(...);

Re: Photon Custom Widgets  
Interesting, based on previous posts I was under the impression that I shouldn't need to call free because the default 
destructor would do that for Pt_Arg_String resources.  Is it possible that the destroy function is not finishing before 
I create the next version of the widget?  In this case the pointer to the previously calloc'd memory would be lost and 
thus exhibit the memory loss I  am experiencing???  Also why the 8k jump?  It's like it is the size for the previous 
widget's data structures that have not been freed yet .... ???
Re: Photon Custom Widgets  
Hi Misha,

Any feedback on my previous questions?  Thanks.

Larry
Re: Photon Custom Widgets  
1. The destructor code doesn’t track allocations in a special way. It simply saves the addresses of memory blocks in 
the widget members. Your code was simply overwriting a member with a new value. This causes the old block to be lost. 
The destructor will “clean-up” the last allocated block – which was yours, but not the original one. That is a leak.
2. Memory allocation routines request more memory from the system (when needed) in 8KB blocks. 
Re: Photon Custom Widgets  
Thank you for your response Misha.  I understand point 2, but still don't understand point one.

Why wouldn't the destructor clean-up code finish before the pointer is reassigned in the defaults function?

My test program continually creates and destroys the window that the custom widget is in.  Shouldn't the destruction 
code finish execution before the next window and widget is created?

Thanks Larry
Re: Photon Custom Widgets  
When you assign a new value to a member the previous value is lost. There is no destructor called when you assign– this
 is “C”. The destructors are called when you change a member through libph, or when you destroy your widget, again 
through libph.
Re: Photon Custom Widgets  
Hello Misha,

My test application continually creates and destroys windows with the custom widget in it.  i.e. create window with 
custom widget, destroy window, create window with custom widget, destroy window etc.

I am expecting that destroying the previous window will clean up the allocated memory before my next window/custom 
widget is created and its default function called which then allocates another chunk.

Larry
Re: Photon Custom Widgets  
Good Morning Misha,

Any comments on my last post?  Just trying to understand the process.

Thanks.

Larry
Re: Photon Custom Widgets  
It depends on how you create and destroy widgets. Let’s say you use a timer widget (that is inside of your window) 
callback to destroy the window. We can’t immediately free() window’s memory as it would cause a crash in the widget 
library when it continues to process outstanding events/callbacks. When you destroy a widget it is not immediately 
recycled: the widget is marked for destruction; some resources are recycled immediately some not, and later at some “
save” point the remaining parts get recycled. 
Obviously in your case the recycling is done after you create a new widget. This is fine. If your app doesn’t leak 
memory, eventually it will reach a “saturation” point – and won’t grow anymore.
Re: Photon Custom Widgets  
Good Morning Misha,

Thank you very much for the explanation.  This is exactly what I was looking for. 

I believe it explains the behaviour we are experiencing in our application.

Thanks for your patience :-).

Larry