QB64.org Forum

Active Forums => QB64 Discussion => Topic started by: madscijr on May 17, 2021, 05:18:34 pm

Title: _CopyImage crashing my program after a while, can somebody please help?
Post by: madscijr on May 17, 2021, 05:18:34 pm
I'm working on a basic tile-based game engine.

It mostly works, but it seems to crash after a certain number of iterations.

(The program window just closes when the sub PlotTextToScreenFast runs a 3rd time.)

I did a bunch of testing, writing log files, etc, and determined it is dying at the line:
Code: QB64: [Select]
  1. swapcolor& = _CopyImage(handle&, 32)
where the value of handle& = -8191.

However I suspect the problem isn't just that line, because there are other times when it runs with that value and doesn't die.

I have attached the code and associated image files, if anyone wants to try running it.

Just search in the .bas file for the word "crash" where I have marked the lines leading up to the crash.

If you run it you will see a menu.
If you press 4 <ENTER> you will see some graphics and text.
Press <ENTER> again to exit back to the menu.

Repeat above 2 more times.
The 3rd time the program will just die.

Why is this happening?

I am definitely not a programming or QB64 expert, and I have been driving myself crazy trying to figure out what I'm doing wrong.

Any help would be much appreciated!
Title: Re: _CopyImage crashing my program after a while, can somebody please help?
Post by: FellippeHeitor on May 17, 2021, 05:28:50 pm
Every time you call _CopyImage you generate an extra image in memory, as the name implies. Do you ever _FreeImage the unused handles? This sounds like a case of memory leaking.
Title: Re: _CopyImage crashing my program after a while, can somebody please help?
Post by: FellippeHeitor on May 17, 2021, 05:29:32 pm
I'm replying solely based on your post above. I haven't checked your code.
Title: Re: _CopyImage crashing my program after a while, can somebody please help?
Post by: bplus on May 17, 2021, 05:51:02 pm
7K lines, yikes!
Title: Re: _CopyImage crashing my program after a while, can somebody please help?
Post by: madscijr on May 17, 2021, 08:15:13 pm
Every time you call _CopyImage you generate an extra image in memory, as the name implies. Do you ever _FreeImage the unused handles? This sounds like a case of memory leaking.

You know, that could be it!
It is clearing the main screen, tilesets, etc. with _FreeImage at the end, but I think that isn't happening in all the calls that repeat over & over in the main loop!
I'll check and let you know what happens.
Thanks for your reply!
Title: Re: _CopyImage crashing my program after a while, can somebody please help?
Post by: madscijr on May 17, 2021, 08:17:29 pm
7K lines, yikes!

Yeah, I was not really sure where the problem exactly was, so I figured I'd post the whole thing. That's why I said search for the word "crash", lol. We will see if that _FREEIMAGE was the issue...
Title: Re: _CopyImage crashing my program after a while, can somebody please help?
Post by: madscijr on May 17, 2021, 10:34:32 pm
I'm replying solely based on your post above. I haven't checked your code.

I did find a couple of places where there was not _FREEIMAGE and added it, however it is still crashing.

Here are just the 3 routines that seem to have the problem.

The function swapcolor& at the bottom is where the program actually dies.

Do you see any other commands in here other than _COPYIMAGE that might require _FREEIMAGE,
or anything else that looks like it could be causing the program to exit?

Code: QB64: [Select]
  1. ' /////////////////////////////////////////////////////////////////////////////
  2. ' Draw entire array on screen in the specified fonts/colors for each character.
  3.  
  4. ' Like PlotTextToScreen but faster because it uses precalculated coordinates
  5. ' to find the tile on the tile sheet, and the destination on the screen.
  6.  
  7. ' Receives:
  8. ' imgScreen& = handle to screen to draw tile on
  9. ' arrImage() = array of image handles pointing to 16x16 tile sheets of 16x16 pixel tiles colored black (256 tiles)
  10. ' arrTileSheetMap() = array of TileSheetMapType which holds precalculated positions of tiles on tilesheet
  11. ' arrTileMap() = array of TileMapType which holds precalculated positions where tiles go on screen
  12. ' tileWidthPx% = width of tiles in pixels
  13. ' tileHeightPx% = height of tiles in pixels
  14. ' TextInfo = TextInfoType which stores info about the text to plot (# columns, # rows. among other things not used here)
  15. ' arrText(80, 80) = 2D array of PlotTextType which stores character code, forecolor, backcolor, bitmap font's tileset image handle; indexed by arrText(column #, index in arrLineOrder)
  16. ' arrLineOrder(80) AS INTEGER = array storing the row position of lines of text in arrText (done this way to speed up scrolling text)
  17.  
  18. Sub PlotTextToScreenFast(imgScreen&, arrImage() AS Long, arrTileSheetMap() AS TileSheetMapType, arrTileMap() AS TileMapType, tileWidthPx%, tileHeightPx%, TextInfo AS TextInfoType, arrText() AS PlotTextType, arrLineOrder() AS INTEGER)
  19.     Dim dx%
  20.     Dim dy%
  21.     Dim TileNum%
  22.     Dim TileColor&
  23.     DIM BackColor&
  24.     DIM iRowPos%
  25.    
  26.     IF TextInfo.numCols > UBound(arrText, 1) THEN
  27.         TextInfo.numCols = UBound(arrText, 1)
  28.     END IF
  29.     IF TextInfo.numRows > UBound(arrText, 2) THEN
  30.         TextInfo.numRows = UBound(arrText, 2)
  31.     END IF
  32.    
  33.     For dy% = 1 To TextInfo.numRows
  34.         iRowPos% = arrLineOrder(dy%)
  35.         For dx% = 1 To TextInfo.numCols
  36.             TileNum% = arrText(dx%, dy%).charCode
  37.             TileColor& = arrText(dx%, dy%).foreColor
  38.             BackColor& = arrText(dx%, dy%).backColor
  39.            
  40.             IF arrText(dx%, dy%).fontNumber > 0 AND arrText(dx%, dy%).fontNumber < 11 THEN
  41. 'THIS IS WHERE THE PROGRAM CRASHES:
  42.                 DrawColorTileFast imgScreen&, arrImage(arrText(dx%, dy%).fontNumber), arrTileSheetMap(), arrTileMap(), tileWidthPx%, tileHeightPx%, TileNum%, TileColor&, BackColor&, dx%, iRowPos%
  43.             ELSE
  44. 'THIS IS WHERE THE PROGRAM CRASHES:
  45.                 DrawColorTileFast imgScreen&, arrImage(1), arrTileSheetMap(), arrTileMap(), tileWidthPx%, tileHeightPx%, TileNum%, TileColor&, BackColor&, dx%, iRowPos%
  46.             END IF
  47.            
  48.         Next dx%
  49.     Next dy%
  50.    
  51.     _Dest imgScreen&
  52.    
  53. End Sub ' PlotTextToScreenFast
  54.  
  55. ' /////////////////////////////////////////////////////////////////////////////
  56. ' Like DrawColorTile but faster because it uses precalculated coordinates
  57. ' to find the tile on the tile sheet, and the destination on the screen.
  58.  
  59. ' Receives:
  60. ' imgScreen& = handle to screen to draw tile on
  61. ' imgTiles& = handle to 16x16 tile sheet of 16x16 pixel tiles colored black (256 tiles)
  62. ' arrTileSheetMap() = array of TileSheetMapType which holds precalculated positions of tiles on tilesheet
  63. ' arrTileMap() = array of TileMapType which holds precalculated positions where tiles go on screen
  64. ' tileWidthPx% = width of tiles in pixels
  65. ' tileHeightPx% = height of tiles in pixels
  66. ' TileNum% = ordinal number of tile on tile sheet to draw (0-255)
  67. ' TileColor& = color to use for tile
  68. ' BackColor& = color to use for background
  69. ' dx% = column # to draw tile at (where each column is 16 pixels wide)
  70. ' dy% = row # to draw tile at (where each row is 16 pixels high)
  71.  
  72. ' *** QUESTION
  73. ' *** IF THE SUB RECEIVES IMAGE HANDLE PARAMETERS imgScreen&, imgTiles&
  74. ' *** ARE THESE BY REFERENCE?
  75. ' *** IF NOT, DO THESE LOCAL COPIES HAVE TO BE RELEASED WITH _FREEIMAGE ?
  76.  
  77. Sub DrawColorTileFast (imgScreen&, imgTiles&, arrTileSheetMap() AS TileSheetMapType, arrTileMap() AS TileMapType, tileWidthPx%, tileHeightPx%, TileNum%, TileColor&, BackColor&, dx%, dy%)
  78.     DIM ColorSprite&
  79.     DIM UniversalSprite&
  80.    
  81.     ' IS THERE A BACKGROUND COLOR?
  82.     IF BackColor& <> cEmpty& THEN
  83.         ColorSprite& = _NewImage(tileWidthPx%, tileHeightPx%, 32)
  84.         _Dest ColorSprite&
  85.         CLS, BackColor&
  86.        
  87.         ' COPY THE TEMPORARY TILE TO THE SCREEN imgScreen&
  88.         _SOURCE ColorSprite&
  89.         _Dest imgScreen&
  90.        
  91.         _PutImage (arrTileMap(dx%, dy%).xPos, arrTileMap(dx%, dy%).yPos), ColorSprite&, imgScreen&, (0, 0)-(tileWidthPx% - 1, tileHeightPx% - 1) ' portion of source to the top-left corner of the destination page
  92.     END IF
  93.  
  94.     ' CREATE A TEMPORARY TILE TO COLOR
  95.     UniversalSprite& = _NewImage(tileWidthPx%, tileHeightPx%, 32)
  96.    
  97.     ' COPY THE TILE TO THE TEMPORARY ONE
  98.     _SOURCE imgTiles&
  99.     _Dest UniversalSprite&
  100.     _PutImage (0, 0), imgTiles&, UniversalSprite&, (arrTileSheetMap(TileNum%).xStart, arrTileSheetMap(TileNum%).yStart)-(arrTileSheetMap(TileNum%).xEnd, arrTileSheetMap(TileNum%).yEnd)
  101.    
  102.     ' COLOR IN THE TEMPORARY TILE
  103.     ' REPLACING BLACK (THE SOURCE COLOR) WITH THE TILE COLOR
  104. 'THIS IS WHERE THE PROGRAM CRASHES:
  105.     ColorSprite& = swapcolor&(UniversalSprite&, cBlack&, TileColor&)
  106.    
  107.     ' COPY THE TEMPORARY TILE TO THE SCREEN imgScreen&
  108.     _SOURCE ColorSprite&
  109.     _Dest imgScreen&
  110.     _PutImage (arrTileMap(dx%, dy%).xPos, arrTileMap(dx%, dy%).yPos), ColorSprite&, imgScreen&, (0, 0)-(tileWidthPx% - 1, tileHeightPx% - 1) ' portion of source to the top-left corner of the destination page
  111.    
  112.     ' ADDED PER FellipeHeitor
  113.     _FREEIMAGE ColorSprite&
  114.     _FREEIMAGE UniversalSprite&
  115.    
  116. End Sub ' DrawColorTileFast
  117.  
  118. ' /////////////////////////////////////////////////////////////////////////////
  119. ' Image color swap?
  120. ' https://www.qb64.org/forum/index.php?topic=2312.0
  121.  
  122. ' Receives:
  123. ' handle& = image handle to swap colors in
  124. ' oldcolor~& = old color to be replaced
  125. ' newcolor~& = new color
  126.  
  127. ' Return value = image handle to copy of image with the new colors
  128.  
  129. Function swapcolor& (handle&, oldcolor~&, newcolor~&)
  130.     Dim m As _MEM
  131.     DIM a&
  132.     'Dim c As _Unsigned Long
  133.     DIM c~&
  134.    
  135. 'THIS IS WHERE THE PROGRAM CRASHES:
  136.     swapcolor& = _CopyImage(handle&, 32)
  137.    
  138.     m = _MemImage(swapcolor&)
  139.    
  140.     Do Until a& = m.SIZE - 4
  141.         a& = a& + 4
  142.        
  143.         c~& = _MemGet(m, m.OFFSET + a&, _Unsigned Long)
  144.        
  145.         If c~& = oldcolor~& Then
  146.             _MemPut m, m.OFFSET + a&, newcolor~&
  147.         End If
  148.     Loop
  149.    
  150.     _MemFree m
  151.    
  152. End Function ' swapcolor&
  153.  

Title: Re: _CopyImage crashing my program after a while, can somebody please help?
Post by: NOVARSEG on May 17, 2021, 10:38:54 pm
without looking at the code

Say a variable is counting and then suddenly becomes  negative?
Title: Re: _CopyImage crashing my program after a while, can somebody please help?
Post by: FellippeHeitor on May 17, 2021, 10:41:53 pm
When you call Function swapcolor&, it returns a handle that's the newly created image you used _CopyImage for. The variables you eventually use to do variable& = swapcolor&(etc) need freeing too.
Title: Re: _CopyImage crashing my program after a while, can somebody please help?
Post by: madscijr on May 17, 2021, 10:48:53 pm
When you call Function swapcolor&, it returns a handle that's the newly created image you used _CopyImage for. The variables you eventually use to do variable& = swapcolor&(etc) need freeing too.

Yes, it is doing that. The value retrieved from the function in line 105:
Code: QB64: [Select]
  1.     ColorSprite& = swapcolor&(UniversalSprite&, cBlack&, TileColor&)

is freed in line 113:
Code: QB64: [Select]
  1.     _FREEIMAGE ColorSprite&

Is it possible that swapcolor& is causing a memory leak just by being a function?
Would it be better to instead make it a sub and return the value in a parameter?
Title: Re: _CopyImage crashing my program after a while, can somebody please help?
Post by: NOVARSEG on May 17, 2021, 11:00:43 pm
Quote
Do Until a& = m.SIZE - 4
        a& = a& + 4
               
        c~& = _MemGet(m, m.OFFSET + a&, _Unsigned Long)
               
        If c~& = oldcolor~& Then
            _MemPut m, m.OFFSET + a&, newcolor~&
        End If
    Loop

It looks like you are memgetting 4 bytes at a time.  Is a& large enough to hold the  count?

There should be a a& = 0 after the loop or before it?

and is

 DIM a&
    'Dim c As _Unsigned Long
    DIM c~&

a valid way of DIMming?
Title: Re: _CopyImage crashing my program after a while, can somebody please help?
Post by: FellippeHeitor on May 17, 2021, 11:01:59 pm
Try this:

Code: QB64: [Select]
  1. IF ColorSprite& < -1 THEN _FreeImage ColorSprite&
  2. ColorSprite& = swapcolor&(UniversalSprite&, cBlack&, TileColor&)
Title: Re: _CopyImage crashing my program after a while, can somebody please help?
Post by: FellippeHeitor on May 17, 2021, 11:04:01 pm
Also, monitor your program as it runs in Task Manager to see if memory usage is constantly increasing until it crashes, if the above doesn't cut it.
Title: Re: _CopyImage crashing my program after a while, can somebody please help?
Post by: NOVARSEG on May 17, 2021, 11:09:39 pm
Quote
Do Until a& = m.SIZE - 4
        a& = a& + 4
               
        c~& = _MemGet(m, m.OFFSET + a&, _Unsigned Long)
               
        If c~& = oldcolor~& Then
            _MemPut m, m.OFFSET + a&, newcolor~&
        End If
    Loop


 
Quote
a& = a& + 4
               
 c~& = _MemGet(m, m.OFFSET + a&, _Unsigned Long)

the count has gotta  be after 
             
Quote
c~& = _MemGet(m, m.OFFSET + a&, _Unsigned Long)

a& = a& + 4

because the first memget is at byte zero
Title: Re: _CopyImage crashing my program after a while, can somebody please help?
Post by: madscijr on May 17, 2021, 11:15:22 pm
Try this:

Code: QB64: [Select]
  1. IF ColorSprite& < -1 THEN _FreeImage ColorSprite&
  2. ColorSprite& = swapcolor&(UniversalSprite&, cBlack&, TileColor&)

I added this but on its own prog was still crashing, but see next reply to NOVARSEG.
Title: Re: _CopyImage crashing my program after a while, can somebody please help?
Post by: NOVARSEG on May 17, 2021, 11:16:14 pm
sorry  Ok the whole code

Quote
Do Until a& = m.SIZE - 4
                       
        c~& = _MemGet(m, m.OFFSET + a&, _Unsigned Long)
               
        If c~& = oldcolor~& Then
            _MemPut m, m.OFFSET + a&, newcolor~&
       
End If

a& = a& + 4
    Loop

also try

DIM a AS _Unsigned Long



Quote
Do Until a = m.SIZE - 4
                       
        c~& = _MemGet(m, m.OFFSET + a, _Unsigned Long)
               
        If c~& = oldcolor~& Then
            _MemPut m, m.OFFSET + a, newcolor~&
       
End If

a = a + 4
    Loop

Title: Re: _CopyImage crashing my program after a while, can somebody please help?
Post by: madscijr on May 18, 2021, 12:23:47 am
sorry  Ok the whole code
also try
DIM a AS _Unsigned Long

My reply didn't post for some reason. I finally got it to stop crashing with a combination of suggestions - thanks for your help guys!

However seeing this latest message I will have some followup questions tomorrow...

Thanks again
Title: Re: _CopyImage crashing my program after a while, can somebody please help?
Post by: NOVARSEG on May 18, 2021, 01:02:53 am
Sorry again. Lets say m.size = 8 (bytes)

the first 4 bytes are memgetted . byte 0, 1, 2, 3

then

 a = a +4  and right away the condition

DO Until a = m.SIZE - 4 

a = (8 - 4) and that exits the DO  LOOP

but bytes 4, 5, 6, 7 don't get memgetted

so

Quote
DO

    c~& = _MemGet(m, m.OFFSET + a, _Unsigned Long)

    IF c~& = oldcolor~& THEN
       _MemPut m, m.OFFSET + a, newcolor~&

    END IF

    a = a + 4
    IF a = m.size THEN EXIT DO
LOOP

which is one of the weaknesses of DO UNTIL etc

Always use EXIT DO

Do Until a = m.SIZE would work, but  there is no sense in LOOPing an extra time if you don't have to.





Title: Re: _CopyImage crashing my program after a while, can somebody please help?
Post by: SMcNeill on May 18, 2021, 03:09:04 am
Yes, it is doing that. The value retrieved from the function in line 105:
Code: QB64: [Select]
  1.     ColorSprite& = swapcolor&(UniversalSprite&, cBlack&, TileColor&)

is freed in line 113:
Code: QB64: [Select]
  1.     _FREEIMAGE ColorSprite&

Is it possible that swapcolor& is causing a memory leak just by being a function?
Would it be better to instead make it a sub and return the value in a parameter?

The thing is, it seems to me as if there's 3 different areas inside your code where you're calling swapcolor.  Line 2416, 2476, 2586.

Each of these calls to swapcolor is making a duplicate image of your screen (that's what _COPYIMAGE does), and yet there's no call to _FREEIMAGE those images.  Each and every one of these routines need to FREEIMAGE the image when you're finished with it.  Doing it in just one place won't handle the issue.
Title: Re: _CopyImage crashing my program after a while, can somebody please help?
Post by: SMcNeill on May 18, 2021, 03:20:23 am
One option, at least in this case, would be to store and free the images in swapcolor itself, like so:

Code: [Select]
FUNCTION swapcolor& (handle&, oldcolor~&, newcolor~&)
    DIM m AS _MEM
    DIM a&
    DIM c AS _UNSIGNED LONG


    STATIC perma_handle AS LONG 'save  the handle between function calls
    IF perma_handle < -1 THEN _FREEIMAGE perma_handle 'if you've used this swapcolor before, then free the old screen
    perma_handle = _COPYIMAGE(handle&, 32) 'get a copy of the screen
    swapcolor& = perma_handle 'and assign it to the FUNCTION so we can return it back for use elsewhere

    m = _MEMIMAGE(swapcolor&)
    DO
        IF _MEMGET(m, m.OFFSET + a&, _UNSIGNED LONG) = oldcolor~& THEN _MEMPUT m, m.OFFSET + a&, newcolor~&
        a& = a& + 4
    LOOP UNTIL a& = m.SIZE
    _MEMFREE m

END FUNCTION ' swapcolor&
Title: Re: _CopyImage crashing my program after a while, can somebody please help?
Post by: madscijr on May 18, 2021, 08:52:14 am
Thanks for your reply.

The thing is, it seems to me as if there's 3 different areas inside your code where you're calling swapcolor.  Line 2416, 2476, 2586.

Are you looking at the original code? That's why I added
Code: QB64: [Select]
  1.  _FREEIMAGE ColorSprite&
a few lines below each call to swapcolor.

Each of these calls to swapcolor is making a duplicate image of your screen (that's what _COPYIMAGE does), and yet there's no call to _FREEIMAGE those images. 

I am not sending an image of the screen to swapcolor, just a single tile-sized image.

Each and every one of these routines need to FREEIMAGE the image when you're finished with it. 
Doing it in just one place won't handle the issue.

That is a question I had, which is, if a function returns a value directly, like
Code: QB64: [Select]
  1. swapcolor& = _CopyImage(handle&, 32)
you can free the value returned to the calling code outside the function,
but how do you free the function's copy?

One option, at least in this case, would be to store and free the images in swapcolor itself, like so:
Code: [Select]
FUNCTION swapcolor& (handle&, oldcolor~&, newcolor~&)
    STATIC perma_handle AS LONG 'save  the handle between function calls

So wait a minute, if we have a function that sends an image handle back as its return value, it's not enough to do a freeimage on the returned handle in the calling code?

Did you see NOVARSEG's responses regarding the memcopy and the loops inside swapcolor?
It sounds like the swapcolor routine needs some work - although it seems to be working for me after changing the variable types:
Code: QB64: [Select]
  1.     Dim m As _MEM
  2.     DIM a As _OFFSET
  3.  

Thanks again!
Title: Re: _CopyImage crashing my program after a while, can somebody please help?
Post by: NOVARSEG on May 18, 2021, 06:52:10 pm
trying out some tests with m.size
keep getting "cannot convert _OFFSET type to other types" error

I have never been able to get m.size to work. In DO LOOPs FOR NEXT LOOPS it just don't work for me.  Maybe the version Im using is outdated?

It looks like m.size is a pointer (_OFFSET)  why?

Like b = m.size is impossible

Another thing,   m.size is redundant, you can get the same value with

_WIDTH * _HEIGHT  * 4

The only thing I got to work is PRINT m.size

but this crashes

  FOR T = 0 TO m.size - 1 STEP 4
Title: Re: _CopyImage crashing my program after a while, can somebody please help?
Post by: SMcNeill on May 18, 2021, 07:11:59 pm
M.size is a pointer, as it points to an offset of memory.  In 32-bit QB64, it’s only 4-bytes in size.  In 64-bit QB64, it’s 8-bytes.

Make your variables _OFFSETs when working with M.SIZE and you won’t have any issues.  Or convert your offset to a suitable integer value as below:


DIM x AS INTEGER
DIM m AS _MEM
m = _MEM(x)
PRINT m.OFFSET
PRINT ConvertOffset(m.OFFSET)


FUNCTION ConvertOffset&& (value AS _OFFSET)
$CHECKING:OFF
DIM m AS _MEM 'Define a memblock
m = _MEM(value) 'Point it to use value
$IF 64BIT THEN
    'On 64 bit OSes, an OFFSET is 8 bytes in size.  We can put it directly into an Integer64
    _MEMGET m, m.OFFSET, ConvertOffset&& 'Get the contents of the memblock and put the values there directly into ConvertOffset&&
$ELSE
    'However, on 32 bit OSes, an OFFSET is only 4 bytes.  We need to put it into a LONG variable first
    _MEMGET m, m.OFFSET, temp& 'Like this
    ConvertOffset&& = temp& 'And then assign that long value to ConvertOffset&&
$END IF
_MEMFREE m 'Free the memblock
$CHECKING:ON
END FUNCTION
Title: Re: _CopyImage crashing my program after a while, can somebody please help?
Post by: NOVARSEG on May 18, 2021, 07:19:16 pm
PRINT m.OFFSET
PRINT ConvertOffset(m.OFFSET)

did you mean m.size ?
Title: Re: _CopyImage crashing my program after a while, can somebody please help?
Post by: SMcNeill on May 18, 2021, 07:58:12 pm
PRINT m.OFFSET
PRINT ConvertOffset(m.OFFSET)

did you mean m.size ?

Sure.  M.OFFSET is an offset.  M.SIZE is an offset.  M.ELEMENTSIZE is an offset.  You can convert any of those with the above.  (Or any other offset.)
Title: Re: _CopyImage crashing my program after a while, can somebody please help?
Post by: NOVARSEG on May 18, 2021, 10:44:58 pm
i DIMensioned T as _OFFSET but

   
Quote
'FOR T = 0 TO 800 * 600 * 4 - 1 STEP 4
        FOR T = 0 TO m.size - 1 STEP 4
            B = _MEMGET(m, m.OFFSET + T, _UNSIGNED _BYTE)
            G = _MEMGET(m, m.OFFSET + T + 1, _UNSIGNED _BYTE)
            R = _MEMGET(m, m.OFFSET + T + 2, _UNSIGNED _BYTE)
            IF B > 1 THEN B = B - 1
            'IF B = 1 THEN B = 0
            IF G > 1 THEN G = G - 1
            ' IF G = 1 THEN G = 0
            IF R > 1 THEN R = R - 1
            'IF R = 1 THEN R = 0
            _MEMPUT m, m.OFFSET + T, B
            _MEMPUT m, m.OFFSET + T + 1, G
            _MEMPUT m, m.OFFSET + T + 2, R
        NEXT T

still crashes
Title: Re: _CopyImage crashing my program after a while, can somebody please help?
Post by: NOVARSEG on May 18, 2021, 11:09:13 pm
ok  this works

   
Quote
DIM Z AS _UNSIGNED LONG
    DIM W AS _MEM
    W = _MEM(m.SIZE)
    _MEMGET W, W.OFFSET, Z



    'FOR T = 0 TO 800 * 600 * 4 - 1 STEP 4
    FOR T = 0 TO Z - 1 STEP 4
        'PRINT T
        B = _MEMGET(m, m.OFFSET + T, _UNSIGNED _BYTE)
        G = _MEMGET(m, m.OFFSET + T + 1, _UNSIGNED _BYTE)
        R = _MEMGET(m, m.OFFSET + T + 2, _UNSIGNED _BYTE)
        IF B > 1 THEN B = B - 1
        'IF B = 1 THEN B = 0
        IF G > 1 THEN G = G - 1
        ' IF G = 1 THEN G = 0
        IF R > 1 THEN R = R - 1
        'IF R = 1 THEN R = 0
        _MEMPUT m, m.OFFSET + T, B
        _MEMPUT m, m.OFFSET + T + 1, G
        _MEMPUT m, m.OFFSET + T + 2, R
    NEXT T

_MEMGET W, W.OFFSET, Z is just the plain _MEMGET. It works a bit different  than the _MEMGET function

 the _MEMGET function

Z = _MEMGET(W, W.OFFSET, _UNSIGNED LONG)

Ok i gonna show that method too
Quote

    DIM Z AS _UNSIGNED LONG
    DIM W AS _MEM
    W = _MEM(m.SIZE)
    Z = _MEMGET(W, W.OFFSET, _UNSIGNED LONG)
   

    'FOR T = 0 TO 800 * 600 * 4 - 1 STEP 4
    FOR T = 0 TO Z - 1 STEP 4
        'PRINT T
        B = _MEMGET(m, m.OFFSET + T, _UNSIGNED _BYTE)
        G = _MEMGET(m, m.OFFSET + T + 1, _UNSIGNED _BYTE)
        R = _MEMGET(m, m.OFFSET + T + 2, _UNSIGNED _BYTE)
        IF B > 1 THEN B = B - 1
        'IF B = 1 THEN B = 0
        IF G > 1 THEN G = G - 1
        ' IF G = 1 THEN G = 0
        IF R > 1 THEN R = R - 1
        'IF R = 1 THEN R = 0
        _MEMPUT m, m.OFFSET + T, B
        _MEMPUT m, m.OFFSET + T + 1, G
        _MEMPUT m, m.OFFSET + T + 2, R
    NEXT T

works the same.

the whole program to see it work. Mess with m.size until it crashes

Code: QB64: [Select]
  1.  
  2. DIM SHARED screenx%, screeny%, tx1%, ty1%, tx2%, ty2%, x1%, y1%, x2%, y2%, d%, handle2&
  3.  
  4. 'DIM T AS _OFFSET
  5. DIM handle AS LONG
  6. screenx% = 800
  7. screeny% = 600
  8.  
  9. handle = _NEWIMAGE(screenx%, screeny%, 32)
  10.  
  11. m = _MEMIMAGE(handle)
  12.  
  13. SCREEN handle
  14.  
  15.  
  16. ' create new black image with alpha channel
  17. 'handle2& = _NEWIMAGE(screenx%, screeny%, 32)
  18. '_DEST handle2&
  19. 'LINE (0, 0)-(screenx%, screeny%), _RGBA(0, 0, 0, 255), BF
  20. '_DEST 0
  21.  
  22. tx1% = screenx% * RND
  23. ty1% = screeny% * RND
  24. tx2% = screenx% * RND
  25. ty2% = screeny% * RND
  26. x1% = screenx% * RND
  27. y1% = screeny% * RND
  28. x2% = screenx% * RND
  29. y2% = screeny% * RND
  30. d% = 3
  31.  
  32.     COLOR _RGB(256 * RND, 256 * RND, 256 * RND)
  33.     ' smearfx
  34.  
  35.     DIM W AS _MEM
  36.     W = _MEM(m.SIZE)
  37.     Z = _MEMGET(W, W.OFFSET, _UNSIGNED LONG)
  38.    
  39.  
  40.     'FOR T = 0 TO 800 * 600 * 4 - 1 STEP 4
  41.     FOR T = 0 TO Z - 1 STEP 4
  42.         'PRINT T
  43.         B = _MEMGET(m, m.OFFSET + T, _UNSIGNED _BYTE)
  44.         G = _MEMGET(m, m.OFFSET + T + 1, _UNSIGNED _BYTE)
  45.         R = _MEMGET(m, m.OFFSET + T + 2, _UNSIGNED _BYTE)
  46.         IF B > 1 THEN B = B - 1
  47.         'IF B = 1 THEN B = 0
  48.         IF G > 1 THEN G = G - 1
  49.         ' IF G = 1 THEN G = 0
  50.         IF R > 1 THEN R = R - 1
  51.         'IF R = 1 THEN R = 0
  52.         _MEMPUT m, m.OFFSET + T, B
  53.         _MEMPUT m, m.OFFSET + T + 1, G
  54.         _MEMPUT m, m.OFFSET + T + 2, R
  55.     NEXT T
  56.  
  57.     IF x1% < tx1% THEN
  58.         x1% = x1% + d%
  59.     ELSE
  60.         x1% = x1% - d%
  61.     END IF
  62.     IF ABS(x1% - tx1%) < d% THEN
  63.         tx1% = screenx% * RND
  64.     END IF
  65.  
  66.     IF y1% < ty1% THEN
  67.         y1% = y1% + d%
  68.     ELSE
  69.         y1% = y1% - d%
  70.     END IF
  71.     IF ABS(y1% - ty1%) < d% THEN
  72.         ty1% = screeny% * RND
  73.     END IF
  74.  
  75.     IF x2% < tx2% THEN
  76.         x2% = x2% + d%
  77.     ELSE
  78.         x2% = x2% - d%
  79.     END IF
  80.     IF ABS(x2% - tx2%) < d% THEN
  81.         tx2% = screenx% * RND
  82.     END IF
  83.  
  84.     IF y2% < ty2% THEN
  85.         y2% = y2% + d%
  86.     ELSE
  87.         y2% = y2% - d%
  88.     END IF
  89.     IF ABS(y2% - ty2%) < d% THEN
  90.         ty2% = screeny% * RND
  91.     END IF
  92.  
  93.     LINE (x1%, y1%)-(x2%, y2%)
  94.  
  95. SUB smearfx ()
  96.     _LIMIT 50
  97.     LINE (0, 0)-(screenx%, screeny%), _RGBA(0, 0, 0, 1), BF
  98.     _PUTIMAGE (0, 0), handle2&, 0
  99.     LINE (x1%, y1%)-(x2%, y2%)
  100.     _DISPLAY
  101.