Rolando V. RaqueñoSunday, October 18, 2015 Modal Widgets, Pointers, and Memory Leaks.

Post on 01-Jan-2016

217 views 1 download

Transcript of Rolando V. RaqueñoSunday, October 18, 2015 Modal Widgets, Pointers, and Memory Leaks.

Rolando V. Raqueño Thursday, April 20, 2023

Modal Widgets, Pointers, and Memory Leaks

Rolando V. Raqueño Thursday, April 20, 2023

Modal Widgets

• Modal Widgets also known as pop-up widgets are a means to simplify a GUI interface by allowing an input window to be presented to the user at an appropriate time

• Because a new window is created and destroyed, there needs to be a mechanism to pass the values specified to the used back to the calling widget.

Rolando V. Raqueño Thursday, April 20, 2023

Variables inside a Widget

• Remember that variables defined in a widget only exist as long as that widget exists

• We have to somehow pass out any values defined to a calling function

Rolando V. Raqueño Thursday, April 20, 2023

pop_fslider Case Study

• Problem: We want to create a simple slider that a user can call from the IDL prompt and return to the calling routine a floating point value reflecting the position of the floating point slider (CW_FSLIDER)

IDL> a = pop_fslider()

Rolando V. Raqueño Thursday, April 20, 2023

pop_fslider.pro (initial version - Widget Definition)

function pop_fslider

base = Widget_Base( /column )

fslider = CW_Fslider( base, /edit )

quit_button = Widget_Button( base, value="Quit", event_pro='quit_event' )

Widget_Control, base, /realize

global_data={ fslider_id: fslider, fslider_value: 0.0 }

Widget_Control, base, set_uvalue=global_data

Xmanager, 'pop_fslider', base, event_handler='pop_fslider_event'

Widget_Control, base, get_uvalue=global_data

print,’In Widget Definition=‘, global_data.fslider_value

return, global_data.fslider_value

end

Rolando V. Raqueño Thursday, April 20, 2023

pop_fslider.pro (initial version -

Event Handler Definition)pro pop_fslider_event, event Widget_Control, event.top, get_uvalue=global_data Widget_Control, global_data.fslider_id,

get_value=fslider_value global_data.fslider_value=fslider_value print,’In Event Handler =‘, global_data.fslider_value Widget_Control, event.top, set_uvalue=global_dataend

pro quit_event, event Widget_Control, event.top, /destroyend

Rolando V. Raqueño Thursday, April 20, 2023

pop_fslider.pro (initial version output)

IDL> a=pop_fslider()In Event Handler = 44.0000In Event Handler = 39.0000In Event Handler = 39.0000In Event Handler = 42.0000% WIDGET_CONTROL: Invalid widget identifier: 1.% Execution halted at: POP_FSLIDER 28 pop_fslider.pro

% $MAIN$

Rolando V. Raqueño Thursday, April 20, 2023

pop_fslider.pro (initial version - Widget Definition)

function pop_fslider base = Widget_Base( /column ) fslider = CW_Fslider( base, /edit ) quit_button = Widget_Button( base, value="Quit",

event_pro='quit_event' ) Widget_Control, base, /realize global_data={ fslider_id: fslider, fslider_value: 0.0 } Widget_Control, base, set_uvalue=global_data Xmanager, 'pop_fslider', base,

event_handler='pop_fslider_event' Widget_Control, base, get_uvalue=global_data print,’In Widget Definition=‘, global_data.fslider_value return, global_data.fslider_valueend

Rolando V. Raqueño Thursday, April 20, 2023

pop_fslider.pro (initial version - Event Definition)

• This does not work because the widget has already been destroyed and along with it the uvalue that was being stored

• To make this work, we need to use what IDL calls handles (or in C/C++ the concept of pointers)

Rolando V. Raqueño Thursday, April 20, 2023

IDL Pointers

Rolando V. Raqueño Thursday, April 20, 2023

What are Pointers?• Pointers are special variables that point to

memory locations that are explicitly allocated by the user.

• It is different from other variables in that the memory location pointed to by a handle are persistent (i.e., they exist from one routine to another)

• It is also the user’s responsibility to destroy the allocated memory

Rolando V. Raqueño Thursday, April 20, 2023

Uses of Handles

• Management of persistent data

• Minimizes passing around large data structures

• Linked lists data structures

• Tree data structures

Rolando V. Raqueño Thursday, April 20, 2023

Syntax for managing Pointers

• Ptr_new (Create a NULL pointer)IDL> image_pointer = ptr_new()

• Ptr_new (Pointer to existing data)IDL> image = bindgen(5,5)IDL> image_pointer = ptr_new(image)

• To access values referenced by pointerIDL> print, (*image_pointer)[0,0]

Rolando V. Raqueño Thursday, April 20, 2023

Sample use of Handle RoutinesIDL> image=bindgen(5,5)IDL> image_pointer = ptr_new(image)IDL> help,imageIMAGE BYTE = Array[5, 5]IDL> help, image_pointerIMAGE_POINTER POINTER = <PtrHeapVar5>

IDL> print, (*image_pointer)[0,0]

Rolando V. Raqueño Thursday, April 20, 2023

pop_fslider.pro (new version - Widget Definition)

function pop_fslider ... Widget_Control, base, /realize pointer = ptr_new(0.0) global_data={ fslider_id: fslider, ptr: pointer } Widget_Control, base, set_uvalue=global_data Xmanager, 'pop_fslider', base,

event_handler='pop_fslider_event' fslider_value = *pointer return, fslider_valueend

Rolando V. Raqueño Thursday, April 20, 2023

pop_fslider.pro (new version -

Event Handler Definition)pro pop_fslider_event, event Widget_Control, event.top, get_uvalue=global_data Widget_Control, global_data.fslider_id,

get_value=fslider_value pointer = global_data.ptr *pointer = fslider_value print,’In Event Handler =‘, fslider_valueend

pro quit_event, event Widget_Control, event.top, /destroyend

Rolando V. Raqueño Thursday, April 20, 2023

Result of pop_fslider.pro

IDL> a=pop_fslider()In Event Handler = 40.0000In Event Handler = 43.0000In Event Handler = 42.0000IDL> print,a 42.0000

Rolando V. Raqueño Thursday, April 20, 2023

Get_preview_image EXAMPLE

A more convoluted example of pointers to a structure containing

pointers.

Rolando V. Raqueño Thursday, April 20, 2023

Get_preview_image.pro

• Allows you to make the following call at the IDL command line

IDL> a=get_preview_image()

• A widget pops up that allows you to select and preview the image

• When done, variable ‘a’ contains the image

Rolando V. Raqueño Thursday, April 20, 2023

Screenshot of get_preview_image

Rolando V. Raqueño Thursday, April 20, 2023

Widget Definition of get_preview_image.pro

function get_preview_image base = Widget_Base( Title='Enter Value', /column ) window_id = Widget_Draw(base, xsize=256, ysize=256) file_button_id=Widget_Button(base,value="File",event_pro='file_event') quit_button_id=Widget_Button(base,value="Quit",event_pro='quit_event') Widget_Control, base, /realize Widget_Control, window_id, get_value=display_id image_ptr = ptr_new() global_data = { window: window_id, display: display_id, $ file_button: file_button_id, $ quit_button: quit_button_id,image: image_ptr } global_ptr = ptr_new( global_data ) Widget_Control, base, set_uvalue=global_ptr Xmanager,'get_preview_image',base image = *((*global_ptr).image) return, imageend

Rolando V. Raqueño Thursday, April 20, 2023

Event Handler of get_preview_image.pro

pro file_event, event file_name = pickfile() print,"Reading in image ...“ & s = systime(/seconds) read_ppm, file_name, image e = systime(/seconds) & print,"Done", e-s,"Seconds“ & print,"" Widget_Control, event.top, get_uvalue=global_data display_id = (*global_data).display wset, display_id tvscl, congrid(image, 256, 256) image_ptr = (*global_data).image image_ptr = ptr_new( image ) (*global_data).image=image_ptrend

pro quit_event, event Widget_Control, event.top, /destroyend

Rolando V. Raqueño Thursday, April 20, 2023

Program seems to run fine

• Test with your favorite image file

• Next,– Create a 10,000 x 10,000 pgm test image

Rolando V. Raqueño Thursday, April 20, 2023

To create a LARGE test image

% pgmramp –ellipse 10000 10000 > pgmramp.pgm

Rolando V. Raqueño Thursday, April 20, 2023

Try to run the program 10 times

IDL> a=get_preview_image()

IDL> a=get_preview_image()

IDL> a=get_preview_image()

IDL> a=get_preview_image()

IDL> a=get_preview_image()

Rolando V. Raqueño Thursday, April 20, 2023

Program Bombs after several tries

Reading in image ...% Compiled module: READ_PPM.Done 10.323603Seconds

% Compiled module: CONGRID.Reading in image ...Done 10.746588Seconds

Reading in image ...Done 11.441382Seconds

Reading in image ...Done 22.284706Seconds

% XMANAGER: Caught unexpected error from client application. Message follows...

% Unable to allocate memory: to make array.

Rolando V. Raqueño Thursday, April 20, 2023

It Dies because…

• There is a memory leak

• This occurs when the program does not free up memory allocated when using pointers

• Repeated runs in the event handler causes memory to be eaten up until there is very little left

Rolando V. Raqueño Thursday, April 20, 2023

FIX to Event Handler of get_preview_image.pro

pro file_event, event file_name = pickfile() print,"Reading in image ...“ & s = systime(/seconds) read_ppm, file_name, image e = systime(/seconds) & print,"Done", e-s,"Seconds“ & print,"" Widget_Control, event.top, get_uvalue=global_data display_id = (*global_data).display wset, display_id tvscl, congrid(image, 256, 256) image_ptr = (*global_data).image ptr_free, image_ptr image_ptr = ptr_new( image ) (*global_data).image=image_ptrend

pro quit_event, event Widget_Control, event.top, /destroyend

Rolando V. Raqueño Thursday, April 20, 2023

Program should now work

• Ptr_free will make sure that the previous pointer reference will be deallocated

Rolando V. Raqueño Thursday, April 20, 2023

Moral

• Pointers can save memory and burden of passing around large structure

• Difficult to interpret dereferencing of pointers

• Memory Leaks are prevalent requiring repeated tests with memory intensive data sets