GAL memory allocation fixes.

Vertex memory allocation uses malloc and realloc without checking the
result.  Throw exceptions that can be caught in the DoRepaint() method
in EDA_DRAW_PANEL_GAL when malloc and realloc return a null pointer.
This commit is contained in:
Wayne Stambaugh 2021-02-22 08:15:09 -05:00
parent 09d3667bce
commit be8327bd54
9 changed files with 56 additions and 29 deletions

View File

@ -239,7 +239,7 @@ void EDA_DRAW_PANEL_GAL::DoRePaint()
m_gal->DrawCursor( m_viewControls->GetCursorPosition() );
}
catch( std::runtime_error& err )
catch( std::exception& err )
{
if( GAL_FALLBACK != m_backend )
{

View File

@ -49,7 +49,7 @@ using namespace KIGFX;
CACHED_CONTAINER::CACHED_CONTAINER( unsigned int aSize ) :
VERTEX_CONTAINER( aSize ),
m_item( NULL ),
m_item( nullptr ),
m_chunkSize( 0 ),
m_chunkOffset( 0 ),
m_maxIndex( 0 )
@ -61,7 +61,7 @@ CACHED_CONTAINER::CACHED_CONTAINER( unsigned int aSize ) :
void CACHED_CONTAINER::SetItem( VERTEX_ITEM* aItem )
{
assert( aItem != NULL );
assert( aItem != nullptr );
unsigned int itemSize = aItem->GetSize();
m_item = aItem;
@ -74,7 +74,7 @@ void CACHED_CONTAINER::SetItem( VERTEX_ITEM* aItem )
void CACHED_CONTAINER::FinishItem()
{
assert( m_item != NULL );
assert( m_item != nullptr );
unsigned int itemSize = m_item->GetSize();
@ -94,7 +94,7 @@ void CACHED_CONTAINER::FinishItem()
if( itemSize > 0 )
m_items.insert( m_item );
m_item = NULL;
m_item = nullptr;
m_chunkSize = 0;
m_chunkOffset = 0;
@ -106,11 +106,11 @@ void CACHED_CONTAINER::FinishItem()
VERTEX* CACHED_CONTAINER::Allocate( unsigned int aSize )
{
assert( m_item != NULL );
assert( m_item != nullptr );
assert( IsMapped() );
if( m_failed )
return NULL;
return nullptr;
unsigned int itemSize = m_item->GetSize();
unsigned int newSize = itemSize + aSize;
@ -121,7 +121,7 @@ VERTEX* CACHED_CONTAINER::Allocate( unsigned int aSize )
if( !reallocate( newSize ) )
{
m_failed = true;
return NULL;
return nullptr;
}
}
@ -147,7 +147,7 @@ VERTEX* CACHED_CONTAINER::Allocate( unsigned int aSize )
void CACHED_CONTAINER::Delete( VERTEX_ITEM* aItem )
{
assert( aItem != NULL );
assert( aItem != nullptr );
assert( m_items.find( aItem ) != m_items.end() || aItem->GetSize() == 0 );
int size = aItem->GetSize();

View File

@ -41,7 +41,9 @@
using namespace KIGFX;
CACHED_CONTAINER_GPU::CACHED_CONTAINER_GPU( unsigned int aSize ) :
CACHED_CONTAINER( aSize ), m_isMapped( false ), m_glBufferHandle( -1 )
CACHED_CONTAINER( aSize ),
m_isMapped( false ),
m_glBufferHandle( -1 )
{
m_useCopyBuffer = GLEW_ARB_copy_buffer;
@ -57,7 +59,7 @@ CACHED_CONTAINER_GPU::CACHED_CONTAINER_GPU( unsigned int aSize ) :
glGenBuffers( 1, &m_glBufferHandle );
glBindBuffer( GL_ARRAY_BUFFER, m_glBufferHandle );
glBufferData( GL_ARRAY_BUFFER, m_currentSize * VERTEX_SIZE, NULL, GL_DYNAMIC_DRAW );
glBufferData( GL_ARRAY_BUFFER, m_currentSize * VERTEX_SIZE, nullptr, GL_DYNAMIC_DRAW );
glBindBuffer( GL_ARRAY_BUFFER, 0 );
checkGlError( "allocating video memory for cached container" );
}
@ -100,7 +102,7 @@ void CACHED_CONTAINER_GPU::Unmap()
glUnmapBuffer( GL_ARRAY_BUFFER );
checkGlError( "unmapping vertices buffer" );
glBindBuffer( GL_ARRAY_BUFFER, 0 );
m_vertices = NULL;
m_vertices = nullptr;
checkGlError( "unbinding vertices buffer" );
}
catch( const std::runtime_error& err )
@ -147,7 +149,7 @@ bool CACHED_CONTAINER_GPU::defragmentResize( unsigned int aNewSize )
wxASSERT( eaBuffer == 0 );
#endif /* __WXDEBUG__ */
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, newBuffer );
glBufferData( GL_ELEMENT_ARRAY_BUFFER, aNewSize * VERTEX_SIZE, NULL, GL_DYNAMIC_DRAW );
glBufferData( GL_ELEMENT_ARRAY_BUFFER, aNewSize * VERTEX_SIZE, nullptr, GL_DYNAMIC_DRAW );
checkGlError( "creating buffer during defragmentation" );
ITEMS::iterator it, it_end;
@ -244,7 +246,7 @@ bool CACHED_CONTAINER_GPU::defragmentResizeMemcpy( unsigned int aNewSize )
wxASSERT( eaBuffer == 0 );
#endif /* __WXDEBUG__ */
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, newBuffer );
glBufferData( GL_ELEMENT_ARRAY_BUFFER, aNewSize * VERTEX_SIZE, NULL, GL_DYNAMIC_DRAW );
glBufferData( GL_ELEMENT_ARRAY_BUFFER, aNewSize * VERTEX_SIZE, nullptr, GL_DYNAMIC_DRAW );
newBufferMem = static_cast<VERTEX*>( glMapBuffer( GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY ) );
checkGlError( "creating buffer during defragmentation" );

View File

@ -49,6 +49,9 @@ CACHED_CONTAINER_RAM::CACHED_CONTAINER_RAM( unsigned int aSize ) :
checkGlError( "generating vertices buffer" );
m_vertices = static_cast<VERTEX*>( malloc( aSize * VERTEX_SIZE ) );
if( !m_vertices )
throw std::bad_alloc();
}
@ -93,7 +96,7 @@ bool CACHED_CONTAINER_RAM::defragmentResize( unsigned int aNewSize )
VERTEX* newBufferMem = static_cast<VERTEX*>( malloc( aNewSize * VERTEX_SIZE ) );
if( !newBufferMem )
return false;
throw std::bad_alloc();
defragment( newBufferMem );

View File

@ -41,6 +41,13 @@ NONCACHED_CONTAINER::NONCACHED_CONTAINER( unsigned int aSize ) :
m_freePtr( 0 )
{
m_vertices = static_cast<VERTEX*>( malloc( aSize * sizeof( VERTEX ) ) );
// Unfortunately we cannot remove the use of malloc here because realloc is used in
// the Allocate method below. The new operator behavior is mimicked here so that a
// malloc failure can be caught in the OpenGL initialization code further up the stack.
if( !m_vertices )
throw std::bad_alloc();
memset( m_vertices, 0x00, aSize * sizeof( VERTEX ) );
}
@ -74,7 +81,7 @@ VERTEX* NONCACHED_CONTAINER::Allocate( unsigned int aSize )
}
else
{
return NULL;
throw std::bad_alloc();
}
}

View File

@ -61,7 +61,7 @@ VERTEX_CONTAINER::VERTEX_CONTAINER( unsigned int aSize ) :
m_freeSpace( aSize ),
m_currentSize( aSize ),
m_initialSize( aSize ),
m_vertices( NULL ),
m_vertices( nullptr ),
m_failed( false ),
m_dirty( true )
{

View File

@ -42,7 +42,7 @@ using namespace KIGFX;
VERTEX_MANAGER::VERTEX_MANAGER( bool aCached ) :
m_noTransform( true ),
m_transform( 1.0f ),
m_reserved( NULL ),
m_reserved( nullptr ),
m_reservedSpace( 0 )
{
m_container.reset( VERTEX_CONTAINER::MakeContainer( aCached ) );
@ -68,18 +68,18 @@ void VERTEX_MANAGER::Unmap()
bool VERTEX_MANAGER::Reserve( unsigned int aSize )
{
assert( m_reservedSpace == 0 && m_reserved == NULL );
assert( m_reservedSpace == 0 && m_reserved == nullptr );
// flag to avoid hanging by calling DisplayError too many times:
static bool show_err = true;
m_reserved = m_container->Allocate( aSize );
if( m_reserved == NULL )
if( m_reserved == nullptr )
{
if( show_err )
{
DisplayError( NULL, wxT( "VERTEX_MANAGER::Reserve: Vertex allocation error" ) );
DisplayError( nullptr, wxT( "VERTEX_MANAGER::Reserve: Vertex allocation error" ) );
show_err = false;
}
@ -106,18 +106,18 @@ bool VERTEX_MANAGER::Vertex( GLfloat aX, GLfloat aY, GLfloat aZ )
--m_reservedSpace;
if( m_reservedSpace == 0 )
m_reserved = NULL;
m_reserved = nullptr;
}
else
{
newVertex = m_container->Allocate( 1 );
}
if( newVertex == NULL )
if( newVertex == nullptr )
{
if( show_err )
{
DisplayError( NULL, wxT( "VERTEX_MANAGER::Vertex: Vertex allocation error" ) );
DisplayError( nullptr, wxT( "VERTEX_MANAGER::Vertex: Vertex allocation error" ) );
show_err = false;
}
@ -138,11 +138,11 @@ bool VERTEX_MANAGER::Vertices( const VERTEX aVertices[], unsigned int aSize )
// Obtain pointer to the vertex in currently used container
VERTEX* newVertex = m_container->Allocate( aSize );
if( newVertex == NULL )
if( newVertex == nullptr )
{
if( show_err )
{
DisplayError( NULL, wxT( "VERTEX_MANAGER::Vertices: Vertex allocation error" ) );
DisplayError( nullptr, wxT( "VERTEX_MANAGER::Vertices: Vertex allocation error" ) );
show_err = false;
}
@ -217,7 +217,7 @@ void VERTEX_MANAGER::ChangeItemDepth( const VERTEX_ITEM& aItem, GLfloat aDepth )
VERTEX* VERTEX_MANAGER::GetVertices( const VERTEX_ITEM& aItem ) const
{
if( aItem.GetSize() == 0 )
return NULL; // The item is not stored in the container
return nullptr; // The item is not stored in the container
return m_container->GetVertices( aItem.GetOffset() );
}

View File

@ -54,13 +54,22 @@ public:
return true;
}
///< @copydoc VERTEX_CONTAINER::SetItem()
virtual void SetItem( VERTEX_ITEM* aItem ) override;
///< @copydoc VERTEX_CONTAINER::FinishItem()
virtual void FinishItem() override;
///< @copydoc VERTEX_CONTAINER::Allocate()
/**
* Return allocated space for the requested number of vertices associated with the
* current item (set with SetItem()).
*
* The allocated space is added at the end of the chunk used by the current item and
* may serve to store new vertices.
*
* @param aSize is the number of vertices to be allocated.
* @return Pointer to the allocated space.
* @throw bad_alloc exception if allocation fails.
*/
virtual VERTEX* Allocate( unsigned int aSize ) override;
///< @copydoc VERTEX_CONTAINER::Delete()

View File

@ -41,6 +41,12 @@ class SHADER;
class NONCACHED_CONTAINER : public VERTEX_CONTAINER
{
public:
/**
* Contruct a non-cached container object.
*
* @param aSize is the size of the cache.
* @throw bad_alloc exception if memory allocation fails.
*/
NONCACHED_CONTAINER( unsigned int aSize = DEFAULT_SIZE );
virtual ~NONCACHED_CONTAINER();