September 25, 2020, 02:34:39 AM

Author Topic: BlitzMaxNG Garbage collector issues  (Read 737 times)

Offline Ashmoor

  • Jr. Member
  • **
  • Posts: 79
Re: BlitzMaxNG Garbage collector issues
« Reply #15 on: June 17, 2020, 12:36:43 AM »
@derron
I finally processed all the hints. Thank you!

I didn't know Funtion/Method arguments take precedence over Fields or Globals, now I do.

Regarding writefile, I didn't know that it deletes all content of the file upon opening it. I thought that it does what pressing insert does when typing.

So initiating a pixmap like this: basePM:TPixmap = LockImage(img) does not need UnlockImage(img)?


Offline Ashmoor

  • Jr. Member
  • **
  • Posts: 79
Re: BlitzMaxNG Garbage collector issues
« Reply #16 on: June 17, 2020, 01:01:09 AM »
I updated the code:

Code: BlitzMax
  1. SuperStrict
  2.  
  3.  
  4.  
  5. Global myImg:TImage=LoadImage("graphics/p1_wallpaper.bmp")
  6.  
  7. Const BI_RGB:Int = 0
  8.  
  9. Const SPI_SETDESKWALLPAPER:Int = 20
  10. Const SPIF_UPDATEINIFILE:Int = 01
  11.  
  12.  
  13. '-----------------------------------------
  14. '
  15. ' save an image as a bmp file
  16. '
  17. '------------------------------------------
  18. Global  bfh_Type:Short
  19. Global  bfh_Size:Int
  20. Global  bfh_Reserved:Int = 0
  21. Global  bfh_OffBits:Int
  22.  
  23. Global bfh_header_size:Int = 2 + 4 + 4 + 4
  24. Global cnt#=0
  25.  
  26. '----------------------------------------------------------------
  27.  
  28. '----------------------------------------------------------------
  29.  
  30.  
  31. Global wallPath$=CurrentDir()+"/graphics/savedwallpp.bmp"
  32. Print wallPath
  33. Print "proc wp:"+(CurrentDir()+"/graphics/savedwallpp.bmp")
  34. Global blackAlpha:Float=0.2
  35.  
  36. Graphics 800,600
  37. SetBlend ALPHABLEND
  38.  
  39. Repeat
  40.         Cls
  41.                 DrawImage (myImg,0,0)
  42.                 SetAlpha (blackAlpha)
  43.                 SetColor(0,0,0)
  44.                 DrawRect(0,0,800,600)
  45.                 SetColor(255,255,255)
  46.                 SetAlpha(1.0)
  47.         Flip
  48.        
  49.         If KeyHit(KEY_ESCAPE) Or AppTerminate() Then End
  50.         If KeyHit(KEY_W) Then
  51.                 'GCSuspend()
  52.                 'AddBlackToImage(myImg,blackAlpha)
  53.                 SaveBitmapFromImage(AddBlackToImage(myImg,blackAlpha)) 
  54.                        
  55.                 'Wallpaper_Set(wallPath) 'CurrentDir()+"/graphics/savedwallpp.bmp"             
  56.                 cnt:+1
  57.                 'GCResume()
  58.         EndIf
  59.  
  60.         If KeyHit (KEY_P) Then blackAlpha:+0.1
  61.         If KeyHit(KEY_O) Then blackAlpha:-0.1  
  62.        
  63.  
  64.        
  65. Forever
  66.  
  67.  
  68. SaveBitmapFromImage(AddBlackToImage( myImg))
  69. Wallpaper_Set(wallPath) 'CurrentDir()+"/graphics/savedwallpp.bmp"
  70.  
  71. Wallpaper_Set(wallPath) 'CurrentDir()+"/graphics/savedwallpp.bmp"
  72.  
  73. '----------------------------------------------------------------
  74.  
  75.  
  76.  
  77. Extern "Win32"
  78.         Function SystemParametersInfo:Int(action:Int, param:Int, vparam:Byte Ptr, winini:Int) "win32"="WINBOOL __stdcall  SystemParametersInfo(UINT ,UINT ,PVOID ,UINT )!" '"SystemParametersInfoA@16"
  79.         Function SystemParametersInfoW:Int(uiAction:UInt, uiParam:UInt, pvParam:Byte Ptr, fWinIni:UInt) "win32"="WINBOOL __stdcall  SystemParametersInfoW(UINT ,UINT ,PVOID ,UINT )!"
  80.         'Function GetLastError() = "GetLastError@0"
  81. End Extern
  82.  
  83. Function Wallpaper_Set(filename:Byte Ptr)
  84. 'note: filename must be real path of the image, not truncated relative path.
  85.         Print "filename:"+filename[0]
  86.         Local res:Int   'this is to check if the wallpaper was set or an error happened
  87.         res=SystemParametersInfo(SPI_SETDESKWALLPAPER, Null, filename, SPIF_UPDATEINIFILE)
  88.         Print "res:"+res
  89.        
  90. EndFunction
  91.  
  92.  
  93.  
  94. Type BitmapInfoHeader
  95.         Field   biSize:Int
  96.         Field   biWidth:Int
  97.         Field   biHeight:Int
  98.         Field   biPlanes:Short
  99.         Field   biBitCount:Short
  100.         Field   biCompression:Int
  101.         Field   biSizeImage:Int
  102.         Field   biXPelsPerMeter:Int
  103.         Field   biYPelsPerMeter:Int
  104.         Field   biClrUsed:Int
  105.         Field   biClrImportant:Int
  106. EndType
  107.  
  108.  
  109. Function Img_ToBmp2:Int(img:TImage, file:TStream)
  110.        
  111.     Print "ImgToBMP start"
  112.         Local pxmp:TPixmap
  113.         Local y:Int
  114.         Local bank1:TBank
  115.  
  116.     pxmp = LockImage(img, , True, False)
  117.         If (pxmp = Null)
  118.                 Return False
  119.     EndIf
  120.        
  121.     file = TStream(file)
  122.         Local ptr1:Byte Ptr
  123.         ptr1 = pxmp.pixels      
  124.  
  125.                
  126.         bank1 = CreateStaticBank(ptr1, pxmp.pitch )
  127.  
  128.         For y = 0 To 1000
  129.         WriteBank(bank1, file, 0, pxmp.pitch )
  130.                 Print " test loop "+y
  131.         Next
  132.    
  133.         UnlockImage(img)
  134.    
  135.         Print "imgTOBMP done "
  136.     Return True
  137.  
  138. EndFunction
  139.  
  140.  
  141. 'Summary: Writes an TImage to an open file stream as a BMP format.
  142. Function Img_ToBmp:Int(img:TImage, file:TStream)
  143.         Local pxmp:TPixmap, x:Int, y:Int, ptr1:Byte Ptr
  144.         Local r:Int, g:Int, b:Int
  145.         Local bank1:TBank, size:Int
  146.         Local file_size:Int, data_size:Int
  147.         Local bih:BitmapInfoHeader=New BitmapInfoHeader
  148.        
  149.         Print "ImgToBMP start"
  150.        
  151.         pxmp = LockImage(img, , True, False)
  152.         If (pxmp = Null)
  153.                 Return False
  154.         EndIf
  155.        
  156.         file = LittleEndianStream(file)
  157.        
  158.         If (pxmp.format <> PF_BGR888)
  159.                 pxmp = pxmp.Convert(PF_BGR888)
  160.         EndIf
  161.        
  162.         ptr1 = pxmp.pixels
  163.        
  164.         data_size = pxmp.height * pxmp.pitch
  165.         file_size = data_size + bfh_header_size + SizeOf(bih)
  166.        
  167.         'go at start of file
  168.         SeekStream(file, 0)
  169.        
  170.         'write file header
  171.        
  172.         bfh_Type = Asc("B") + ( Asc("M") Shl 8 )
  173.         WriteShort(file, bfh_Type)
  174.        
  175.         bfh_Size = file_size
  176.         WriteInt(file, bfh_Size)
  177.        
  178.         bfh_Reserved = 0
  179.         WriteInt(file, bfh_Reserved)
  180.        
  181.         bfh_OffBits= bfh_header_size + SizeOf(bih)
  182.         WriteInt(file, bfh_OffBits)
  183.        
  184.        
  185.         'write info header
  186.         bih = New BitmapInfoHeader
  187.         bih.biSize = SizeOf(bih)
  188.         bih.biWidth = pxmp.width
  189.         bih.biHeight = pxmp.height
  190.         bih.biPlanes = 1
  191.         bih.biBitCount = 24
  192.         bih.biCompression = BI_RGB
  193.         bih.biSizeImage = data_size
  194.         bih.biXPelsPerMeter = 2835
  195.         bih.biYPelsPerMeter = 2835
  196.         bih.biClrUsed = 0
  197.         bih.biClrImportant = 0
  198.         bank1 = CreateStaticBank(bih, SizeOf(bih) )
  199.         WriteBank(bank1, file, 0, SizeOf(bih) )
  200.        
  201.         'write it top-down
  202.         ptr1 :+ (data_size - pxmp.pitch)
  203.         For y = 0 Until pxmp.height
  204.                
  205.                 bank1 = CreateStaticBank(ptr1, pxmp.pitch )
  206.                 WriteBank(bank1, file, 0, pxmp.pitch )
  207.                
  208.                 ptr1 :- pxmp.pitch
  209.         Next
  210.        
  211.        
  212.         UnlockImage(img)
  213.         Print "imgTOBMP done"
  214.         Return True
  215. EndFunction
  216.  
  217.  
  218. 'Summary: Opens a stream and writes ssImg to it as BMP format.
  219. Function SaveBitmapFromImage:Int(ssImg:TImage)
  220. 'note: this will save a bmp to my roaming file.
  221.         Print "SBFI start"
  222.         Local path:String = "graphics/savedwallpp.bmp"
  223.         Local file:TStream = WriteFile(path)
  224.        
  225.         If Not file
  226.                 Print "failed to open existing or to create new file ~q" + path + "~q for writing."
  227.                 Return False
  228.         Else
  229.                 If Img_ToBmp(ssImg,file)
  230.                         Print path + " image was created"
  231.                         CloseStream(file)
  232.                         Return True
  233.                 EndIf
  234.         EndIf
  235.        
  236. End Function
  237.  
  238.  
  239.  
  240. Function AddBlackToImage:TImage(img:TImage, alpha:Float=0.3)
  241. 'alpha is in the transparency with witch the black box is drawn on top
  242.         Print "add black to img start"
  243.         Local w:Int = ImageWidth(img)
  244.         Local h:Int = ImageHeight(img)
  245.        
  246.         Local r:Float, g:Float, b:Float
  247.         Local pixel:Int
  248.         Local imgPixel:TRGBvector= New TRGBvector
  249.        
  250.         Local basePM:TPixmap = LockImage(img)
  251.         Local finalPM:TPixmap = TPixmap.Create(w, h, PF_RGB888)
  252.        
  253.         Print "here1"
  254.        
  255.         'basePM =
  256.         UnlockImage(img)
  257.        
  258.         Print "here2"
  259.         For Local i:Int = 0 Until h
  260.                 For Local j:Int = 0 Until w
  261.                         pixel = ReadPixel(basePM, j, i)
  262.                         'imgPixel = GetRGBvectorFromPixel(pixel)
  263.                         GetRGBvectorFromPixel1(pixel, imgPixel)
  264.                         imgPixel.DarkenByPercent(alpha)
  265.                         pixel = GetPixelFromRGBvector(imgPixel)
  266.                         WritePixel(finalPM, j, i, pixel)
  267.                 Next
  268.         Next
  269.         Print "here3"
  270.         Local retImg:TImage = LoadImage(finalPM)
  271.        
  272.         Print "add black to img done"
  273.        
  274.         Return retImg
  275.        
  276. End Function
  277.  
  278.  
  279. Type TRGBvector
  280.         Field r:Float
  281.         Field g:Float
  282.         Field b:Float
  283.        
  284.         Method DrawSelf()
  285.                 Local rStr:String
  286.                 Local gStr:String
  287.                 Local bStr:String
  288.                
  289.                 rStr = r
  290.                 rStr = rStr[..5]
  291.                 gStr = g
  292.                 gStr = gStr[..5]
  293.                 bStr = b
  294.                 bStr = bStr[..5]
  295.                
  296.                 DrawText("r:" + rStr + " g:" + gStr + " b:" + bStr, 10, 30)
  297.                
  298.         End Method
  299.        
  300.         'Summary: Adds a little bit of black into
  301.         Method DarkenByPercent(alpha:Float)
  302.         'This is equivalent to drawing a black pixel on top of current one using "alpha" transparncy
  303.                 r = Truncate255(r - (r * alpha))
  304.                 g = Truncate255(g - (g * alpha))
  305.                 b = Truncate255(b - (b * alpha))
  306.         EndMethod
  307.        
  308.         'Summary: Tweaks brightness of all channels (-1 to 1)
  309.         Method AdjustBrightness(br:Float)
  310.         'This will add/remove a percent of each channel, acting somewhat like overlay layer.
  311.         'it is not perfect because on the negative side of the curve it should
  312.         'remove a percent of the missing value
  313.         'eg: 245 has 10 missing so at br=-1.0 it should be -235, that woud be similar to the br>0
  314.                
  315.                 r = Truncate255(r + (r * br))
  316.                 g = Truncate255(g + (g * br))
  317.                 b = Truncate255(b + (b * br))
  318.                
  319.         EndMethod
  320.        
  321.         'Summary: Sets RGB values
  322.         Method SetRGB:Int(r:Int, g:Int, b:Int)
  323.                 Self.r = r
  324.                 Self.g = g
  325.                 Self.b = b
  326.         End Method
  327.        
  328. EndType
  329.  
  330.  
  331. 'Summary: Returns RGBvector from int pixel value
  332. Function GetRGBvectorFromPixel:TRGBvector(rgb:Int)
  333.         If cnt>=1 Then Print "here 4"
  334.         Local rgbV:TRGBvector= New TRGBvector
  335.         If cnt>=1 Then Print "here 5"
  336.         Local r:Float = ((rgb Shr 16) & $ff) / 255:Float
  337.         Local g:Float = ((rgb Shr 8) & $ff) / 255:Float
  338.         Local b:Float = ((rgb) & $ff) / 255:Float
  339.        
  340.         r = r * 255; g = g * 255; b = b * 255
  341.        
  342.         rgbV.r = r; rgbV.g = g; rgbV.b = b
  343.        
  344.         Return rgbV
  345.        
  346. End Function
  347.  
  348. 'Summary: Returns RGBvector from int pixel value
  349. Function GetRGBvectorFromPixel1(rgb:Int, rgbV:TRGBvector Var)
  350.        
  351.         Local r:Float = ((rgb Shr 16) & $ff) / 255:Float
  352.         Local g:Float = ((rgb Shr 8) & $ff) / 255:Float
  353.         Local b:Float = ((rgb) & $ff) / 255:Float
  354.        
  355.         r = r * 255; g = g * 255; b = b * 255
  356.        
  357.         rgbV.r = r; rgbV.g = g; rgbV.b = b
  358.        
  359. End Function
  360.  
  361.  
  362. 'Summary: truncates a value to the interval [0,255]
  363. Function Truncate255:Float(val:Float)
  364.         If val < 0 Then val = 0
  365.         If val > 255 Then val = 255
  366.        
  367.         Return val
  368. End Function
  369.  
  370. Function GetPixelFromRGBvector:Int(vec:TRGBvector)
  371.         Local pixel:Int
  372.  
  373.         Local r:Int = vec.r
  374.         Local g:Int = vec.g
  375.         Local b:Int = vec.b
  376.        
  377.         pixel = $ff000000 | (r Shl 16) | (g Shl 8) | b
  378.  
  379.        
  380.         Return pixel
  381.  
  382. End Function
  383.  

and tried it with GDB again, here is the output:

Code: [Select]
Starting program: M:\gamedev\33 mosaics\programming tests\bmx NG save bitmap.debug.exe
[New Thread 18072.0x3cdc]
warning: FTH: (18072): *** Fault tolerant heap shim applied to current process. This is usually due to previous crashes. ***
[New Thread 18072.0x3490]
[New Thread 18072.0x35a4]
[New Thread 18072.0x3934]
[New Thread 18072.0x35b4]
[New Thread 18072.0x2f00]
[New Thread 18072.0x23cc]
[New Thread 18072.0x3870]
[New Thread 18072.0x3b24]
[New Thread 18072.0x2cdc]
[New Thread 18072.0x4880]
[New Thread 18072.0x41c]
[New Thread 18072.0x1218]
[New Thread 18072.0x27b8]
[Thread 18072.0x27b8 exited with code 0]
[New Thread 18072.0x468]
[New Thread 18072.0x2758]
[New Thread 18072.0x4290]
[New Thread 18072.0xf08]
[New Thread 18072.0x49ac]
[New Thread 18072.0xc2c]
[New Thread 18072.0x19c0]
[Thread 18072.0xc2c exited with code 0]
[Thread 18072.0x19c0 exited with code 0]
[Thread 18072.0x49ac exited with code 0]
[New Thread 18072.0x4834]
[New Thread 18072.0x143c]
[New Thread 18072.0x32e0]
[New Thread 18072.0x3500]
[New Thread 18072.0x3bc8]
warning: HEAP[bmx NG save bitmap.debug.exe]:
warning: Invalid address specified to RtlValidateHeap( 00E70000, 0BE69A20 )

Thread 1 received signal SIGTRAP, Trace/breakpoint trap.
0x775f9c44 in ntdll!RtlCaptureStackContext () from C:\WINDOWS\SYSTEM32\ntdll.dll
(gdb) bt
#0  0x775f9c44 in ntdll!RtlCaptureStackContext () from C:\WINDOWS\SYSTEM32\ntdll.dll
#1  0x77596057 in ntdll!RtlValidateHeap () from C:\WINDOWS\SYSTEM32\ntdll.dll
#2  0x77574640 in ?? () from C:\WINDOWS\SYSTEM32\ntdll.dll
#3  0x723b64e7 in ?? () from C:\WINDOWS\SYSTEM32\AcLayers.dll
#4  0x75677409 in msvcrt!free () from C:\WINDOWS\System32\msvcrt.dll
#5  0x00e70000 in ?? ()
#6  0x00558d6d in ?? ()
#7  0xf8e483ec in ?? ()
#8  0x64084d8b in ?? ()
#9  0x0018158b in ?? ()
Backtrace stopped: Cannot access memory at address 0x8b55ff8f
(gdb)

Offline Ashmoor

  • Jr. Member
  • **
  • Posts: 79
Re: BlitzMaxNG Garbage collector issues
« Reply #17 on: June 17, 2020, 01:04:37 AM »
I think @Pingus is right, the crash is somewhere here

Code: BlitzMax
  1. Function Img_ToBmp2:Int(img:TImage, file:TStream)
  2.        
  3.     Print "ImgToBMP start"
  4.         Local pxmp:TPixmap
  5.         Local y:Int
  6.         Local bank1:TBank
  7.  
  8.     pxmp = LockImage(img, , True, False)
  9.         If (pxmp = Null)
  10.                 Return False
  11.     EndIf
  12.        
  13.     file = TStream(file)
  14.         Local ptr1:Byte Ptr
  15.         ptr1 = pxmp.pixels      
  16.  
  17.                
  18.         bank1 = CreateStaticBank(ptr1, pxmp.pitch )
  19.  
  20.         For y = 0 To 1000
  21.         WriteBank(bank1, file, 0, pxmp.pitch )
  22.                 Print " test loop "+y
  23.         Next
  24.    
  25.         UnlockImage(img)
  26.    
  27.         Print "imgTOBMP done "
  28.     Return True
  29.  
  30. EndFunction
  31.  

I removed this block and it didn't crash anymore.


Offline Henri

  • Sr. Member
  • ****
  • Posts: 256
Re: BlitzMaxNG Garbage collector issues
« Reply #18 on: June 17, 2020, 08:08:59 AM »
Hi,

put a Debugstop command at the start of the function and execute lines one by one and even follow the execution inside a function with jump button (next to step button). You can check your variables at the debug window and see if they are what you expect.

If there is a big loop and you don't want to iterate all items just put another Debugstop at a convenient location and you can halt the execution after loop or make it conditional like "If i = 500 Then Debugstop" ..

-Henri
- Got 01100011 problems, but the bit ain't 00000001

Offline Derron

  • Hero Member
  • *****
  • Posts: 3178
Re: BlitzMaxNG Garbage collector issues
« Reply #19 on: June 17, 2020, 10:09:21 AM »
@derron
[...]
So initiating a pixmap like this: basePM:TPixmap = LockImage(img) does not need UnlockImage(img)?

You should still use "UnlockImage(img)" after you finished modifying the "basePM" (if you do). For now the comman does nothing - but maybe after an update it would...hmm reupload the pixmap to the gpu (as texture) or emit an event or ... dunno what else it could do.

The important part of the code change above was, to avoid
basePM = newly created pixmap
basePM = some other pixmap

as the first line would create a pixmap (memory operation) just to then free it later on as another pixmap is assigned.



I had issues with "Banks" too (when I wrote some streamed audio stuff). No crashed but stuff which somehow did not work as I thought it should - but in this case it was surely my fault (doing dumb stuff :D).




bye
Ron

Offline Brucey

  • Full Member
  • ***
  • Posts: 134
Re: BlitzMaxNG Garbage collector issues
« Reply #20 on: June 17, 2020, 11:27:47 AM »
Hallo.

Seems to be an issue when freeing a previous TBank... The error implies the GC header has become corrupt somehow.

Code: [Select]
Thread 1 received signal SIGSEGV, Segmentation fault.
GC_free (p=0xb34d5cc) at D:/000_programming/BlitzMaxNG/mod/brl.mod/blitz.mod/bdwgc/malloc.c:588
588         sz = (size_t)hhdr->hb_sz;
(gdb) bt
#0  GC_free (p=0xb34d5cc) at D:/000_programming/BlitzMaxNG/mod/brl.mod/blitz.mod/bdwgc/malloc.c:588
#1  0x0000000000463cfa in bbMemFree (p=<optimized out>)
    at D:/000_programming/BlitzMaxNG/mod/brl.mod/blitz.mod/blitz_memory.c:26
#2  0x000000000041cd71 in _brl_bank_TBank_Delete (o=0xb2ed440)
    at D:/000_programming/BlitzMaxNG/mod/brl.mod/bank.mod/bank.bmx:41
#

Offline Brucey

  • Full Member
  • ***
  • Posts: 134
Re: BlitzMaxNG Garbage collector issues
« Reply #21 on: June 17, 2020, 11:41:34 AM »
I've committed a fix to TBank which prevents the attempted freeing of static memory.

If you don't want to update to the latest, this is how Delete() currently looks:
Code: [Select]
Method Delete()
Assert Not _locked
If _capacity>=0 And Not _static MemFree _buf
End Method

Offline Derron

  • Hero Member
  • *****
  • Posts: 3178
Re: BlitzMaxNG Garbage collector issues
« Reply #22 on: June 17, 2020, 12:59:35 PM »
I think it might have the same issue in "brl.audiosample" ... deleting stuff even if created with "CreateStatic".

Edit ... strike that, there is a "capacity check" in there. But maybe brl.audiosample could learn from TBank and introduce a _static flag as it could have a valid "capacity" then.

bye
Ron

Offline Pingus

  • Full Member
  • ***
  • Posts: 110
Re: BlitzMaxNG Garbage collector issues
« Reply #23 on: June 17, 2020, 02:33:31 PM »
Thanks Brucey, the fix seems working fine !

@Ashmoor
Replace the delete function in bank.bmx

\mod\brl.mod\bank.mod

And recompile the mod.


Offline Ashmoor

  • Jr. Member
  • **
  • Posts: 79
Re: BlitzMaxNG Garbage collector issues
« Reply #24 on: June 18, 2020, 04:45:09 AM »
Thanks guys, I updated Delete() rebuilt modules and works perfectly now.

 

SimplePortal 2.3.6 © 2008-2014, SimplePortal