From 4c0ab7a739085a32688f34947c0b1812a31d92d7 Mon Sep 17 00:00:00 2001 From: aura Date: Wed, 11 Mar 2026 00:41:44 +0100 Subject: fix mem leaks, string convenience funcs --- src/game.cpp | 5 +++-- src/game/world/bsp.cpp | 7 ++++--- src/render/gl_batch.h | 8 ++++++-- src/util/allocator.h | 50 ++++++++++++++++++++++++++++++++++++--------- src/util/profiler.h | 4 +--- src/util/string.h | 55 +++++++++++++++++++++++++++++++++++++++++++++++++- 6 files changed, 109 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/game.cpp b/src/game.cpp index 092da55..8497b6a 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -2,6 +2,7 @@ #include #include "game.h" +#include "SDL_keycode.h" #include "game/physics/movement.h" #include "game/world/bsp.h" #include "game/world/draw.h" @@ -18,6 +19,7 @@ #include "gui.h" #include "render/gl_batch.h" #include "util.h" +#include "util/input.h" #include "util/profiler.h" #include "util/time.h" @@ -196,7 +198,6 @@ U8 game_main_loop( GAME_DATA* game ) { _profiled gui_onframe( game ); profiler_draw_tree( game->assets.jpn12 ); - #if defined(DEBUG) && !IS_EDITOR game_draw_fpsoverlay( game ); #endif @@ -204,7 +205,7 @@ U8 game_main_loop( GAME_DATA* game ) { _profiled if( !OK( gl_endframe( gl ) ) ) return 1; - return 0; + return input_is_key_down( SDLK_ESCAPE ); } void game_on_tick( GAME_DATA* game ) { _profiled diff --git a/src/game/world/bsp.cpp b/src/game/world/bsp.cpp index c4928a3..c7d746b 100644 --- a/src/game/world/bsp.cpp +++ b/src/game/world/bsp.cpp @@ -163,7 +163,8 @@ LIST bsp_map_faces_from_walls( WORLD_MAP* map ) { }; } - BSP_FACE f{ .propid = w->propid }; + BSP_FACE f{}; + f.propid = w->propid; f.verts.push( vertices[2] ); f.verts.push( vertices[1] ); f.verts.push( vertices[0] ); @@ -209,8 +210,8 @@ LIST bsp_map_get_faces( WORLD_MAP* map ) { LIST walls = bsp_map_faces_from_walls( map ); LIST floors = bsp_map_faces_from_planes( map ); - ret.emplace_list( walls ); - ret.emplace_list( floors ); + ret.push_list( walls ); + ret.push_list( floors ); return ret; } diff --git a/src/render/gl_batch.h b/src/render/gl_batch.h index e7f979c..31ed0ea 100644 --- a/src/render/gl_batch.h +++ b/src/render/gl_batch.h @@ -80,15 +80,19 @@ inline GL_BATCH* gl_batch_create( template inline void gl_batch_destroy( GL_BATCH* batch ) { glDeleteBuffers( 1, &batch->vbuffer ); - for( auto& it : batch->calls ) + for( auto& it : batch->calls ) { it.textures.clear(); + it.vertices.clear(); + } delete batch; } template inline void gl_batch_empty( GL_BATCH* batch ) { - for( auto& it : batch->calls ) + for( auto& it : batch->calls ) { it.textures.clear(); + it.vertices.clear(); + } batch->calls.clear(); } diff --git a/src/util/allocator.h b/src/util/allocator.h index 64bad23..8b159da 100644 --- a/src/util/allocator.h +++ b/src/util/allocator.h @@ -93,9 +93,15 @@ struct LIST { } data = (T*)malloc( sizeof( T ) * other.capacity ); - memcpy( data, other.data, other.size * sizeof( T ) ); size = other.size; capacity = other.capacity; + if constexpr( __is_trivially_copyable(T) ) + memcpy( data, other.data, other.size * sizeof(T) ); + else { + memset( data, 0, other.capacity * sizeof(T) ); + for( U32 i = 0; i < other.size; i++ ) + data[i] = other.data[i]; + } } LIST& operator=( const LIST& other ) { @@ -107,7 +113,7 @@ struct LIST { data = 0; - if( !other.capacity || !other.size ) { + if( !other.capacity || !other.size || !other.data ) { capacity = 1; size = 0; data = (T*)malloc( sizeof( T ) ); @@ -116,15 +122,26 @@ struct LIST { } data = (T*)malloc( other.capacity * sizeof( T ) ); - memcpy( data, other.data, other.size * sizeof( T ) ); size = other.size; capacity = other.capacity; + if constexpr( __is_trivially_copyable(T) ) + memcpy( data, other.data, other.size * sizeof(T) ); + else { + memset( data, 0, other.capacity * sizeof(T) ); + for( U32 i = 0; i < other.size; i++ ) + data[i] = other.data[i]; + } return *this; } ~LIST() { - free( data ); + if constexpr( !__is_trivially_destructible(T) ) { + for( U32 i = 0; i < size; i++ ) + data[i].~T(); + } + if( data ) + free( data ); } T at( U32 index ) { @@ -136,7 +153,7 @@ struct LIST { return; T* newblock = (T*)malloc( count * sizeof( T ) ); - memset( newblock, 0, capacity * sizeof( T ) ); + memset( newblock, 0, count * sizeof( T ) ); if( data ) { memcpy( newblock, data, size * sizeof( T ) ); free( data ); @@ -221,9 +238,14 @@ struct LIST { // slow - pushes every item individually, calls copy constructors void push_list( LIST& list ) { - list.each( fn( T* item ) { - push( *item ); - } ); + if constexpr( __is_trivially_copyable(T) ) { + emplace_list( list ); + } else { + reserve( list.capacity ); + list.each( fn( T* item ) { + push( *item ); + } ); + } } T pop() { @@ -241,7 +263,7 @@ struct LIST { } T pop_front() { - if( size == 0 ) { + if( size == 0 ) { dlog( "LIST::pop_front() : called on empty list\n" ); abort(); return {}; @@ -256,6 +278,11 @@ struct LIST { if( idx >= size ) return; + if constexpr( !__is_trivially_destructible(T) ) { + data[idx].~T(); + memset( &data[idx], 0, sizeof(T) ); + } + for( U32 i = idx; i < size - 1; i++ ) data[i] = data[i + 1]; @@ -268,6 +295,11 @@ struct LIST { } void clear() { + if constexpr( !__is_trivially_destructible(T) ) { + for( U32 i = 0; i < size; ++i ) + data[i].~T(); + } + size = 0; free( data ); data = (T*)malloc( sizeof( T ) ); diff --git a/src/util/profiler.h b/src/util/profiler.h index c8eea24..7caac96 100644 --- a/src/util/profiler.h +++ b/src/util/profiler.h @@ -66,10 +66,8 @@ inline void __profiler_intern_new_frame( PROFILER_LIST_ENTRY* entry ) { return pe->hash == entry->hash; } ); - if( i != -1 ) { - __profiler_intern_clear_frame( &gprof.frames.data[i] ); + if( i != -1 ) gprof.frames.erase( i ); - } PROFILER_LIST_ENTRY* pne = gprof.frames.push( ne ); for( auto& it : pne->children ) { diff --git a/src/util/string.h b/src/util/string.h index 0781fca..04bd9c6 100644 --- a/src/util/string.h +++ b/src/util/string.h @@ -54,6 +54,14 @@ struct ARRSTR { template struct __str : public LIST { __str() : LIST() {} + __str( U32 count, const CT* str ) : LIST() { + this->data = 0; + this->capacity = 0; + this->reserve( count * 2 ); + memcpy( this->data, str, count ); + this->size = count; + this->data[this->size] = 0; + } __str( const CT* fmt, ... ) : LIST() { va_list args; va_start( args, fmt ); @@ -62,6 +70,7 @@ struct __str : public LIST { U32 c = vsnprintf( 0, 0, fmt, args ); va_end( args ); this->data = 0; + this->capacity = 0; this->reserve( c * 2 ); vsnprintf( this->data, c + 1, fmt, args2 ); this->data[c] = 0; @@ -187,7 +196,10 @@ struct __str : public LIST { return idx_of( str, 0 ); } - U32 idx_of( const CT* str, U32 offset ) { + U32 idx_of( const CT* str, I32 offset ) { + if( offset < 0 ) + offset = this->size + offset; + for( U32 i = offset; i < this->size; ++i ) { U8 found = 1; for( U32 i2 = 0; !!str[i2] && i + i2 < this->size; ++i2 ) { @@ -217,6 +229,47 @@ struct __str : public LIST { return 0; } + LIST<__str> split( const char* where ) { + LIST<__str> ret; + U32 slen = strlen_ct( where ); + + U32 last = 0; + for( U32 i = 0; i < this->size; ++i ) { + for( U32 i2 = 0; i2 < slen; ++i2 ) { + if( this->data[i + i2] != where[i2] ) + break; + + if( i2 == slen - 1 ) { + if( !(last - i) ) + ret.push( "" ); + else + ret.push( __str( i - last, this->data + last ) ); + i += slen; + last = i; + } + } + } + + if( last < this->size - slen ) { + if( !( this->size - last ) ) + ret.push( "" ); + else + ret.push( __str( this->size - last, this->data + last ) ); + } + + return ret; + } + + // can take negative input as offset from end + __str substr( I32 start, I32 end ) { + if( start < 0 ) + start = this->size + start; + if( end < 0 ) + end = this->size + end; + + return __str( end - start, this->data + start ); + } + LIST_ITERATOR end() { return LIST_ITERATOR( this->data + this->size ); } -- cgit v1.2.3