I am designing an ECS and I have a struct that holds two values: an array of integers and a double pointer. I also have another structure that holds a pointer to the previous struct.
I'm able to access to the pointer to the first struct. However, whenever I try to access any of the pointers in the struct, I end up having a memory leak.
Simple Implementation:
#include <stdio.h>
#include <stdlib.h>
#include "queue.h"
#define MAX_ENTITIES 4096
#define MAX_COMPONENTS 16
typedef unsigned int Entity;
typedef struct ENTITYMANAGER {
Queue* available;
unsigned int count;
} ENTITYMANAGER;
typedef void* Component;
typedef struct COMPONENTMANAGER {
unsigned int* count;
Component** available;
} COMPONENTMANAGER;
typedef struct COORDINATOR {
ENTITYMANAGER* entities;
COMPONENTMANAGER* components;
} COORDINATOR;
typedef struct Test {
int num;
char* string;
} Test;
Test* createTestComponent(char* string, int number) {
Test* test = (Test*) malloc(sizeof(Test));
test -> num = number;
test -> string = (string) ? string : "Test Component";
return test;
}
static ENTITYMANAGER* createEntityManager(void) {
ENTITYMANAGER* entities = (ENTITYMANAGER*) malloc(sizeof(ENTITYMANAGER));
entities -> available = queue(MAX_ENTITIES);
entities -> count = 0;
return entities;
}
static COMPONENTMANAGER* createComponentManager(void) {
COMPONENTMANAGER* components = (COMPONENTMANAGER*) malloc(sizeof(COMPONENTMANAGER));
components -> available = (Component**) malloc(sizeof(Component*) * MAX_ENTITIES);
for (int element = 0; element < MAX_ENTITIES; element++)
(components -> available)[element] = (Component*) calloc(MAX_COMPONENTS, sizeof(Component));
components -> count = (int*) calloc(MAX_ENTITIES, sizeof(int));
return components;
}
COORDINATOR* init(void) {
COORDINATOR* coordinator = (COORDINATOR*) malloc(sizeof(COORDINATOR));
coordinator -> entities = createEntityManager();
coordinator -> components = createComponentManager();
return coordinator;
}
Entity createEntity(COORDINATOR* coordinator) {
if (!(coordinator && (coordinator -> entities -> count < MAX_ENTITIES)))
return NULL_ITEM;
Entity entity = front(coordinator -> entities -> available);
dequeue(coordinator -> entities -> available);
(coordinator -> entities -> count)++;
return entity;
}
void createComponent(COORDINATOR* coordinator, Entity entity, int cnum, void* data) {
if (!coordinator)
return;
(coordinator -> components -> available)[entity][cnum] = createTestComponent(data, 5);
(coordinator -> components -> count)[entity]++;
}
int main(int argc, char const *argv[]) {
COORDINATOR* coordinator = init();
Entity test = createEntity(coordinator);
createComponent(coordinator, test, 0, NULL);
Test* component = (Test*) (coordinator -> components -> available)[test][0];
printf("Test Component: (\"%s\", %d)", component -> string, component -> num);
return 0;
}
Queue Implementation: Queue.h
Solution: I had to update my ENTITYMANAGER
creation method, which was causing my Entity
creation returning an out of bound value causing the memory leak. Specifically, I filled the queue which stores the available entity values with valid values.
static ENTITYMANAGER* createEntityManager(void) {
ENTITYMANAGER* entities = (ENTITYMANAGER*) malloc(sizeof(ENTITYMANAGER));
entities -> available = queue(MAX_ENTITIES); entities -> count = 0;
for (Entity entity = 0; entity < MAX_ENTITIES; entity++)
enqueue(entities -> available, entity);
return entities;
}
I suppose there's no memory issue for above code.
I'm just confused you even are not able to access coordinator -> components -> count)[0]
.
It looks like type of Component is a pointer from (components -> available)[itr][stp] = NULL;
. If it's not initialized definitely there will be an error to access it. But there should be no issue to access (coordinator -> components -> count)[0]
.