Getting a segfault that I'm struggling to identify the root cause of, the surface cause is that the object pointer is empty but the root cause for why that object was empty when it should've had a value is currently beyond me, if anyone's able to spot it from the below code &/or the link I'd appreciate the help.
Here's a copy of the main function with a comment added to the line that segfaults:
Code:
PAW_API pawd pawInitStringv( PAWS *str, pawhhs args, va_list va )
{
pawd const buf_opts = PAW_O_CLEAR_NEW | PAW_O_ZERO_TAIL;
pawd need = 0, ate = 0, pos = 0, end = 0, max = 0;
pawd j, leng = pawhhs_length(args);
PAWVA_UDV UDV = {0};
PAWBUF *Cfgs = &(UDV.Cfgs);
PAWBUF *Rdio = &(UDV.Rdio);
PAWVA_RDIO *rdio = NULL;
PAWVA_PUTF *putf = NULL;
PAWVA_DATA *data = NULL;
UDV.args = args;
UDV.options = pawStdOptions;
UDV.scalers = pawStdScalers;
UDV.formats = pawStdFormats;
if ( leng <= 0 )
return -(leng < 0);
rdio = pawInitBuffert( Rdio, sizeof(PAWVA_RDIO), buf_opts, leng );
for ( UDV.i = 0; args[end]; UDV.i = end )
{
pawhhc c = args[end], n = args[++end];
if ( c != '%' )
continue;
/* Should we include % character in snippet? */
end += (n == '%' || !n);
/* Append snippet to list for adding later */
j = Rdio->count;
join_read_string( &UDV, pos, end++ );
rdio = pawSeekBufferi( Rdio, j );
if ( !n || n == '%' || n == '@' || n == '>' )
{
pos = end + 1;
/* Have we escaped a % character? */
switch ( n )
{
case '%': case 0:
rdio->end++;
rdio->len++;
break;
/* Are we taking a new list of options? */
case '<':
UDV.options = va_arg( va, pawva_flag_cb* );
break;
/* Are we taking a new list of scalers? */
case '@':
UDV.scalers = va_arg( va, PAWVA_MODF* );
break;
/* Are we taking a new list of formats? */
case '>':
UDV.formats = va_arg( va, PAWVA_PUTF** );
break;
}
continue;
}
for ( j = 0; joinCBs[j]; ++j )
{
ate = joinCBs[j]( &UDV, pos, end );
if ( ate < 0 )
{
pawTermBuffer( Rdio );
return -1;
}
pos = end + ate;
}
}
/* Collect remaining text */
join_read_string( &UDV, pos, end );
rdio = pawSeekBufferHead( Rdio );
for ( j = 0; j < Rdio->count; ++j, ++rdio )
{
if ( rdio->get > max )
max = rdio->get;
}
max += sizeof(PAWVA_DATA);
/* Work out how many potential characters are needed */
data = pawInitBuffert( Cfgs, max, buf_opts, Rdio->count );
need = 0;
if ( !data )
ate = -1;
else
{
pawd cfg = 0;
rdio = pawSeekBufferHead( Rdio );
data = pawGrowBufferc( Cfgs, 1 );
data->cfg = data + 1;
for ( j = 0; j < Rdio->count; ++j, ++rdio )
{
rdio->data = data;
ate = rdio->readCB( rdio, va );
if ( ate < 0 )
break;
need += ate;
if ( rdio->putf )
{
(void)pawGrowBufferc( Cfgs, ++cfg + 1 );
data = pawSeekBufferi( Cfgs, cfg );
data->cfg = data + 1;
}
}
/* Allocate needed memory and start printing the value to the
* buffer */
ate = -(ate < 0 || !pawInitStringt( str, need ));
for ( cfg = 0; cfg < Cfgs->count; ++cfg )
{
data = pawSeekBufferi( Cfgs, cfg );
putf = data->cb.putf;
if ( ate >= 0 )
ate = putf->join( data, str ); // Segfault occurs here on pawInitStringf( &strbuf, "%u", 10 ) with 3 configs in buffer, should only be 1 config and it should've had the putf member filled by this point
if ( putf->term && data->cfg )
putf->term( data->cfg );
}
if ( ate < 0 )
{
PAW_BREAK;
pawTermString( str );
}
else
{
/* release unneeded memory */
pawTrimBufferc( str, str->count );
}
}
pawTermBuffer( Cfgs );
pawTermBuffer( Rdio );
return (ate < 0) ? -1 : str->count;
}
Next a link for related code:
src/libpaw/global/strbuf.c * 508534bdf007e5b7278aa29ac329e4ec74eb7138 * Lee Shallis / Dragonbuilder * GitLab
The above function is at the bottom of the file.