ds_grid_read() seems to always consume memory

My game currently has a memory leak and will slowly crash. The following code is causing the leak, I've stiped down the code as much as possible to simplify the problem. I realize the code block below serves no functional purpose. I just want to understand it and why its consuming so much memory.

Manually destroying the buffer doesn't help either.

GML:
var npc_size_from_server = buffer_read(buffer, buffer_u32)

// this is a string created on the server using ds_grid_write()
var temp_string = buffer_read(buffer, buffer_string)
var temp_grid = ds_grid_create(NPC_SIZE, npc_size_from_server)

// this read is causing memory to be consumed, dont know why or how to free it
// if i comment out the read line, the memory leak stops
ds_grid_read(temp_grid, temp_string)   
ds_grid_destroy(temp_grid)
 
What is your IDE and runtime version? Having just done my own test on ds_grid_read (IDE 2.3.1.542, RT 2.3.1.409), I don't have any memory leaks:
GML:
// This is in the "Key Down - Space" event, so it's run every frame
// No leaks at all
var g = ds_grid_create(32, 32);
ds_grid_read(g, grid_str);
ds_grid_destroy(g);
Is that example all your code, or is there anything else that might be causing it?
 
I'm using the newest stable build of GMS 2, IDE v2.3.1.542 Runtime v2.3.1.409, same as you, Windows VM. I'm not sure if your test above is equivalent because in my case, the grid that I'm reading from is different every time. My example above is all the uncommented code in the problematic function.

Let me describe how my game works. My game is a multiplayer game. It has both a client and server. The leak is only on the client. When the client is ran under the debugger, the memory will climb at a consistent rate of .01MB. The game uses a global grid named global.npc. This grid acts as the source of true for the current state of all npcs, location, health, etc.

1. Every certain number of steps, the server uses ds_grid_write() to write the grid to a network buffer as a string.
2. The network buffer is then sent out to all currently connected clients.
3. Each client then reads the string from the incoming buffer and then calls ds_grid_read() to get the data into a temp grid.
4. Some changes are made to the temp grid.
5. Temp grid is then copied via ds_grid_copy() to the clients instance of global.npc.

I've done/know the following:

- When I comment out only the ds_grid_read() line, the leak stops.
- I've made sure that any time I'm about to do several writes to a network buffer, I've reset the seek. If my buffers were growing out of control the leak would be present on the server, so this can't be the issue.
- I've went through all the code line by line and made sure in every case were a ds_*_create() was used for a temporary data structure, it was being destroyed at the end of the function or before a function return.

I don't know what else to check. I'll try to replicate this leak in a minimalistic standalone project later tonight. This is starting to look like a bug with ds_grid_read().
 
I figured out what's happening. It's a bug within the ds_grid_read() function.

The leak happens when a developer does the following.

1. Creates a ds_grid and puts at least one string value in it.
2. Uses ds_grid_write to write the grid to a network buffer as a string.
3. On the receiving side of the network buffer, the buffer gets read as a string.
4. ds_grid_read is used to read the string into a grid.

A full working project designed to demo this bug is available at the link below. Usage instructions are within the game its self. All network functionality of the demo is tied to the loopback address, 127.0.0.1.


https://github.com/andrew-klassen/ds_grid_read_bug

The manual states that it is an expectation for a ds_grid to store either a real or string value.

ds grid manual


Neither ds_grid_read or ds_grid_write makes note of this behavior. Although it does note that the read and write functions were intended to be used in file/IO operations.

ds_grid_write
ds_grid_read

I will make an official bug report/support request in addition to this post. If you are a YoYo moderator reading this, please treat this as a critical bug. It has taken me 2 days to figure out what why my game has a memory leak and this bug is going to force me to have to re-write a lot of my code.

Thanks nacho_chicken for verifying that my usage of ds_read was good.
 

chamaeleon

Member
Looks like another missed decrement of a reference count to a string so garbage collection still thinks the string in the grid is referenced, despite the grid being destroyed. I believe the reference count is not decremented either when assigning a numeric value to the grid cell holding a string. Same behavior if one stores an array in the grid cell.
 
Top