What does imagedestroy do?

General FreeBASIC programming questions.
sancho3
Posts: 358
Joined: Sep 30, 2017 3:22

What does imagedestroy do?

Post by sancho3 »

In the following code, 2 any ptrs are created, imgA and imgB.
imgA is int. with a call to imagecreate(). Then imgB = imgA.
The pointers are both pointing to the same memory.
imageDestroy() is called on imgA supposedly deallocating that memory.
At this point shouldn't imgB be pointing to deallocated memory?
imageInfo(imgB) returns a valid image, at the very same memory.
Has anything been deallocated?

Code: Select all

ScreenRes 800, 600, 32
Dim As Any Ptr imgA, imgB
imgA = ImageCreate(100,100,,32)

Line imgA,(0,0)-Step(99,99), RGB(0,255,0)

Put (0,0), imgA, Trans 
imgB = imgA
Put (20,0), imgB, Trans
? ImageInfo(imgA), ImageInfo(imgB), imgA, imgB
ImageDestroy(imgA)
imgA = 0
Put(40,0), imgB, Trans
? ImageInfo(imgA), ImageInfo(imgB), imgA, imgB

sleep
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: What does imagedestroy do?

Post by fxm »

I think ImageDestroy just deals with memory deallocation, but without first modifying its contents.
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: What does imagedestroy do?

Post by dodicat »

The runtime function imagedestroy is written in C of course.
Here is the closest translation i can think of:

Code: Select all

 

#macro TheCfunctionFromTheRuntimeLibrary
FBCALL void fb_GfxImageDestroy(void *image)
{
	if( image == NULL ) return;
	free(((void **)image)[-1]);
}
#endmacro

'=============================================

'#include "crt.bi"
sub fb_GfxImageDestroy(byref image as any ptr)

	if( image = 0 ) then return
 
    'free cast(any ptr ptr,image)[-1]
    
    deallocate cast(any ptr ptr,image)[-1]
	

end sub


ScreenRes 800, 600, 32
Dim As Any Ptr imgA, imgB
imgA = ImageCreate(100,100,,32)

Line imgA,(0,0)-Step(99,99), RGB(0,255,0)

Put (0,0), imgA, Trans 
imgB = imgA
Put (20,0), imgB, Trans
? ImageInfo(imgA), ImageInfo(imgB), imgA, imgB
fb_GfxImageDestroy(imgA)
imgA = 0
Put(40,0), imgB, Trans
? ImageInfo(imgA), ImageInfo(imgB), imgA, imgB

sleep



 
grindstone
Posts: 862
Joined: May 05, 2015 5:35
Location: Germany

Re: What does imagedestroy do?

Post by grindstone »

@sancho3: After deallocation the content of the deallocated memory is no longer defined, so accessing it can cause unexpected behaviour. That's why you should always set the pointer (respectively both pointers, in your case) to 0 after deallocating.
sancho3
Posts: 358
Joined: Sep 30, 2017 3:22

Re: What does imagedestroy do?

Post by sancho3 »

Yes but the bigger picture means you absolutely cannot rely on imageInfo() to return valid results, correct?
How about setting the imgA ptr contents (as integer) to 0 after imageDestroy and before assigning imgA = 0?

Code: Select all

*Cast(integer ptr, imgA) = 0

Code: Select all

ScreenRes 800, 600, 32
#Include "fbgfx.bi"
Dim As FB.image Ptr imgA, imgB
imgA = ImageCreate(100,100,,32)

Line imgA,(0,0)-Step(99,99), RGB(0,255,0)

Put (0,0), imgA, Trans 
imgB = imgA
Put (20,0), imgB, Trans
? ImageInfo(imgA), ImageInfo(imgB), imgA, imgB
Imagedestroy(imgA)
*Cast(integer ptr, imgA) = 0
imgA = 0
Put(40,0), imgB, Trans
? ImageInfo(imgA), ImageInfo(imgB), imgA, imgB

 
sleep
grindstone
Posts: 862
Joined: May 05, 2015 5:35
Location: Germany

Re: What does imagedestroy do?

Post by grindstone »

sancho3 wrote:How about setting the imgA ptr contents (as integer) to 0 after imageDestroy and before assigning imgA = 0?
Noone ever suggested that FB is foolproof. If you intend to produce bugs, you will most likely accomplish it.
sancho3
Posts: 358
Joined: Sep 30, 2017 3:22

Re: What does imagedestroy do?

Post by sancho3 »

Thats obsurd. Why have error messages at all then?

The point here is that imageInfo is presented as a way to tell if your pointer is a valid image. It is not.

Code: Select all

Screenres 800, 600,32
dim As Byte fool = 1
dim as Integer w, h, bypp,pitch, size
Dim As integer Ptr pix_data
? Imageinfo(@fool, w, h, bypp, pitch, pix_data, size)
? w, h, bypp, pitch, pix_data, size 
'Put(0,0), @fool, Trans 	' good luck with this one 
Sleep 

I am not saying it is a bug, but it is most definitely not returning valid information with respect to what the documentation says.
I think at least the manual should be changed reflect that if there is anything at pointer[0] other than 0, imageInfo() will return 0.
Imageinfo cannot be used to test if a pointer is pointing to a valid image.
I think I understand why that is but certainly the documents should reflect that.
paul doe
Moderator
Posts: 1733
Joined: Jul 25, 2017 17:22
Location: Argentina

Re: What does imagedestroy do?

Post by paul doe »

sancho3 wrote:The point here is that imageInfo is presented as a way to tell if your pointer is a valid image. It is not.
Mmm, I see your point. Here's another way, if you need/want to validate an image pointer:

Code: Select all

#include once "fbgfx.bi"

function isImageValid( byval pImage as any ptr ) as boolean
  return( iif( cptr( fb.image ptr, pImage )->type = fb.put_header_new, _
    true, false ) )
end function

screenRes( 800, 600, 32 )

dim as any ptr img = imageCreate( 32, 32 )
dim as byte fool = 1

? isImageValid( img )
? isImageValid( @fool )

sleep()

if( isImageValid( img ) = true ) then
  imageDestroy( img )
end if
Perhaps a suggestion to improve the wiki is in order?
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: What does imagedestroy do?

Post by fxm »

Before talking about updating the documentation, we must first decide if it is a bug or not (about return value of imageinfo ()).
If it's a bug, then fill in a bug report.
If it is not a bug but the expected operating, then only update the documentation.
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: What does imagedestroy do?

Post by MrSwiss »

IMHO: NOT a BUG (rather, expected behaviour!) ...
(cannot read reliably (valid data), what's been destroyed, the IMG Header, here)

It is a simple case of programmers negligence, because of:
a missing ERROR check, in the code!

A simple zero Ptr check, does *the trick* (confirmation of Ptr validity),
before a ImageInfo() call is made (see code below):

Code: Select all

Const As Short  w = 1024, h = 768, cd = 32
Const As ULong  white = &hFFFFFFFF, black = &hFF000000

' MAIN start
ScreenRes(w, h, cd)
Color(black, white) : Cls
Width w \ 8, h \ 16

' works only if screen has been defined !!!
Dim As Any Ptr  pImg1 = ImageCreate(w \ 16, h \ 8)

If pImg1 = 0 Then   ' zero Ptr check
    ? "ImageCreate() failed, exiting ... ";
    Sleep : End 1
End If

' carry on with ImageInfo() because: Ptr is valid
'
ImageDestroy(pImg1) : pImg1 = 0
? "All went well! Press a key to EXIT ... ";

Sleep : End 0
sancho3
Posts: 358
Joined: Sep 30, 2017 3:22

Re: What does imagedestroy do?

Post by sancho3 »

I am on board with it not being a bug.
The problem Mr. Swiss is that imageInfo cannot be relied on as currently described in the docs.
Tell me what is the purpose of the using imageinfo with only the pointer as a parameter?

Code: Select all

? imageInfo(myPointer)

According to the manual, that is a valid FB call. However it tells the programmer absolutely nothing image related. It only tells us if pointer[0] is 0 or non-zero.
This is the function not returning usable information as described by the docs.
ImageInfo() can only be used reliably when it is passed a valid pointer to an image. It is not reliable in any other case.
This is not programmer error, or negligence.
I also agree with both Mr. Swiss and Grindstone that it is the programmers responsibility to track image pointers from start to finish. This is especially true in the absence of a function that can tell you if a block of data is a valid FB.Image type.

@Paul Doe:
If I understand the code correctly it is looking for a valid header?
I imagine it would be incredibly complex to take and 'is_image_valid()' function any farther than that.
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: What does imagedestroy do?

Post by dodicat »

With a 32 bit image which has been imagedestroyed, if a user accidentally uses imageinfo for what remains of this image (the old address), a crash will occur.
For an 8 bit image, imageinfo will return everything as being OK.
So, there is inconsistency.
To be consistent, the address should be manually set to 0 after imagedestroy.

Code: Select all

 

screen 19,32

dim as any ptr im=imagecreate(800,600,,8) '<------ change 8 to 32
imagedestroy im
'im=0
dim as Integer w, h, bypp,pitch,size
Dim As integer Ptr pix_data


print Imageinfo(im, w, h, bypp, pitch, pix_data, size)
print w, h, bypp, pitch, pix_data, size 
sleep
  
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: What does imagedestroy do?

Post by fxm »

No crash for me in both 32-bit and 64-bit.
It must depend on the environment.

But you are right.
If a crashing may occur when calling ScreenInfo on a dangling pointer, the only way to always can call ScreenInfo safely is to set the pointer to null just after ImageDestroy.
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: What does imagedestroy do?

Post by dodicat »

As a small tester:
deallocate cast(any ptr ptr,i)[-1]
seems the same as
imagedestroy(i)

Code: Select all

 
Function Regulate(Byval MyFps As Long,Byref fps As Long) As Long
    Static As Double timervalue,_lastsleeptime,t3,frames
    frames+=1
    If (Timer-t3)>=1 Then t3=Timer:fps=frames:frames=0
    Var sleeptime=_lastsleeptime+((1/myfps)-Timer+timervalue)*1000
    If sleeptime<1 Then sleeptime=1
    _lastsleeptime=sleeptime
    timervalue=Timer
    Return sleeptime
End Function

Sub drawtoImage(myimage as any ptr,myspeed as long,xres as long,yres as long)
    const rad=50
    Static x As Long = 100
    Static y As Long = 100
    Static dx As Long = 2
    Static dy As Long = 2
    Static As Long fps
        x += dx : y += dy
        If x<rad Or x>=xres-rad Then dx = -dx
        If y<rad Or y>=yres-rad Then dy = -dy
        Circle myimage,(x,y),rad,,,,,f
        Draw  String myimage,(20,20),"Framerate = " &fps
        Sleep Regulate(myspeed,fps),1
End Sub

screen 19,32
dim as long framerate=60
do
   dim as any ptr i=imagecreate(800,600,0)
    drawtoImage(i,framerate,800,600)
    put(0,0),i,pset
    'imagedestroy(i)
    deallocate cast(any ptr ptr,i)[-1]
    i=0
    loop until len(inkey)
  
thus this is yet another alternative to screenlock/unlock ... screenset/flip
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: What does imagedestroy do?

Post by MrSwiss »

sancho3 wrote:Tell me what is the purpose of the using imageinfo with only the pointer as a parameter?

Code: Select all

? imageInfo(myPointer)
According to the manual, that is a valid FB call. It only tells us if pointer[0] is 0 or non-zero.
It tells the programmer whether the Ptr is valid, before the 'useful' ImageInfo(this time, with return parameters).
Basically the same, as a zero Ptr check. (in short: you'll have 2 calls, in order to be *on the safe side* !)
sancho3 wrote:This is the function not returning usable information as described by the docs.
Only on the second call, it returns what you call: 'useful'. (details above)
Post Reply