Clean up all refs when a stage ends, print a warning if some leaked

This commit is contained in:
Andrei "Akari" Alexeyev 2017-02-28 16:38:02 +02:00
parent 3b422b803e
commit 4acfc71887
4 changed files with 45 additions and 7 deletions

View file

@ -62,27 +62,40 @@ void delete_all_elements(void **dest, void (callback)(void **, void *)) {
*dest = NULL;
}
#ifdef DEBUG
// #define DEBUG_REFS
#endif
#ifdef DEBUG_REFS
#define REFLOG(...) fprintf(stderr, __VA_ARGS__);
#else
#define REFLOG(...)
#endif
int add_ref(void *ptr) {
int i;
int i, firstfree = -1;
for(i = 0; i < global.refs.count; i++) {
if(global.refs.ptrs[i].ptr == ptr) {
global.refs.ptrs[i].refs++;
REFLOG("increased refcount for %p (ref %i): %i\n", ptr, i, global.refs.ptrs[i].refs);
return i;
} else if(firstfree < 0 && global.refs.ptrs[i].ptr == FREEREF) {
firstfree = i;
}
}
for(i = 0; i < global.refs.count; i++) {
if(global.refs.ptrs[i].ptr == FREEREF) {
global.refs.ptrs[i].ptr = ptr;
global.refs.ptrs[i].refs = 1;
return i;
}
if(firstfree >= 0) {
global.refs.ptrs[firstfree].ptr = ptr;
global.refs.ptrs[firstfree].refs = 1;
REFLOG("found free ref for %p: %i\n", ptr, firstfree);
return firstfree;
}
global.refs.ptrs = realloc(global.refs.ptrs, (++global.refs.count)*sizeof(Reference));
global.refs.ptrs[global.refs.count - 1].ptr = ptr;
global.refs.ptrs[global.refs.count - 1].refs = 1;
REFLOG("new ref for %p: %i\n", ptr, global.refs.count - 1);
return global.refs.count - 1;
}
@ -100,8 +113,30 @@ void free_ref(int i) {
return;
global.refs.ptrs[i].refs--;
REFLOG("decreased refcount for %p (ref %i): %i\n", global.refs.ptrs[i].ptr, i, global.refs.ptrs[i].refs);
if(global.refs.ptrs[i].refs <= 0) {
global.refs.ptrs[i].ptr = FREEREF;
global.refs.ptrs[i].refs = 0;
REFLOG("ref %i is now free\n", i);
}
}
void free_all_refs(void) {
int inuse = 0;
int inuse_unique = 0;
for(int i = 0; i < global.refs.count; i++) {
if(global.refs.ptrs[i].refs) {
inuse += global.refs.ptrs[i].refs;
inuse_unique += 1;
}
}
if(inuse) {
warnx("free_all_refs(): %i refs were still in use (%i unique, %i total allocated)", inuse, inuse_unique, global.refs.count);
}
free(global.refs.ptrs);
memset(&global.refs, 0, sizeof(RefArray));
}

View file

@ -32,4 +32,5 @@ extern void *_FREEREF;
int add_ref(void *ptr);
void del_ref(void *ptr);
void free_ref(int i);
void free_all_refs(void);
#endif

View file

@ -25,6 +25,7 @@ void taisei_shutdown(void) {
if(!config_get_int(CONFIG_NO_AUDIO)) shutdown_sfx();
if(!config_get_int(CONFIG_NO_MUSIC)) shutdown_bgm();
free_all_refs();
free_resources();
video_shutdown();
gamepad_shutdown();

View file

@ -785,6 +785,7 @@ void stage_loop(StageInfo *stage) {
stage->procs->end();
stage_free();
tsrand_switch(&global.rand_visual);
free_all_refs();
}
static void draw_title(int t, StageInfo *info, Alignment al, int x, int y, const char *text, TTF_Font *font, Color *color) {