04 Feb, 2009, Kayle wrote in the 1st comment:
Votes: 0
Ok, so I have a template:

template < size_t N > const char *bitset_string( const std::bitset<N>& bits, const char *const flagarray[] )
{
std::vector< std::string > flags;
static std::string flag_str;

for( size_t x = 0; x < N; ++x )
{
if( bits.test( x ) )
{
// if flagarray were a vector, we'd do x < flagarray.size() or something
assert( x < ( sizeof( flagarray ) / sizeof( char* ) ) );
flags.push_back( flagarray[x] );
}
}
flag_str = join( flags, " " ); // or "," or whatever
return flag_str.c_str( );
}


I use it for turning a bitset into a string of flags on whatever the bitset is part of. Anyway, upon testing it crashes because the assert fails. And I can't for the life of me figure out why.

Here's the call:
ch->pagerf( "  &wSave flags: &W%s\r\n", bitset_string( sysdata->saveFlags, save_flag ) );


The flag array is:
const char *const save_flag[] = { "death", "kill", "passwd", "drop", "put", "give", "auto", "zap",
"auction", "get", "receive", "idle", "backup", "quitbackup", "fill"
};


And the flags are defined as:
/*
* Autosave flags
*/
typedef enum
{
SV_DEATH, SV_KILL, SV_PASSCHG, SV_DROP, SV_PUT, SV_GIVE,
SV_AUTO, SV_ZAPDROP, SV_AUCTION, SV_GET, SV_RECEIVE,
SV_IDLE, SV_BACKUP, SV_QUITBACKUP, SV_FILL, SV_EMPTY,
MAX_AUTOSAVE_FLAG
} autosave_flags;


Now, as this is my first foray into using asserts, I'm not sure what's wrong, or how to fix it, so any insight is appreciated.
04 Feb, 2009, David Haley wrote in the 2nd comment:
Votes: 0
It looks like autosave_flags has slots for EMPTY and MAX_AUTOSAVE_FLAG. If you set N to MAX_AUTOSAVE_FLAG, that means that x will go all the way to SV_EMPTY. But, you don't have a save_flag entry for that. (Why that flag would be set is a good question, though.)

What I'd recommend is to print the values of x, N and sizeof(flagarray)/sizeof(char*) where the assert fails to see what's going on; that should give clues. It's possible that "somebody" (:tongue:) got something wrong somewhere while writing the function distracted by other things :wink:
04 Feb, 2009, Kayle wrote in the 3rd comment:
Votes: 0
Even adding in an entry for empty didn't stop the crashes, so I'm going to crash it again this time in GDB and print everything. :P

And here we have it.
Quote
(gdb) bt
#0 0x000000349ea32f05 in raise () from /lib64/libc.so.6
#1 0x000000349ea34a73 in abort () from /lib64/libc.so.6
#2 0x000000349ea2bef9 in __assert_fail () from /lib64/libc.so.6
#3 0x00000000006172c4 in bitset_string<16ul> (bits=@0x1ee55e8,
flagarray=0x6ad2a0) at templates.h:43
#4 0x00000000006142e2 in do_cset (ch=0x22929a0, argument=0x7fff619b3b04 "")
at sysdata.cpp:492
#5 0x0000000000569887 in interpret (ch=0x22929a0, argument=0x7fff619b3b04 "")
at interp.cpp:461
#6 0x0000000000527960 in game_loop () at comm.cpp:826
#7 0x00000000005291b6 in main (argc=5, argv=0x7fff619b4078) at comm.cpp:518
(gdb) frame 3
#3 0x00000000006172c4 in bitset_string<16ul> (bits=@0x1ee55e8,
flagarray=0x6ad2a0) at templates.h:43
43 assert( x < ( sizeof( flagarray ) / sizeof( char* ) ) );
(gdb) print x
$1 = 2
(gdb) print sizeof( flagarray )
$2 = 8
(gdb) print sizeof( char * )
$3 = 8
(gdb) print (sizeof( flagarray ) / sizeof (char *))
$4 = 1
(gdb) print N
No symbol "N" in current context.
(gdb)
04 Feb, 2009, David Haley wrote in the 4th comment:
Votes: 0
Oh yeah. I forgot that since flag_array is a pointer, it will have a size of 1. That trick only works for arrays for which the compiler knows the size. Eh, I guess you can get rid of the assert :-)
04 Feb, 2009, Kayle wrote in the 5th comment:
Votes: 0
So it just becomes:

template < size_t N > const char *bitset_string( const std::bitset<N>& bits, const char *const flagarray[] )
{
std::vector< std::string > flags;
static std::string flag_str;

for( size_t x = 0; x < N; ++x )
{
if( bits.test( x ) )
flags.push_back( flagarray[x] );
}
flag_str = join( flags, " " ); // or "," or whatever
return flag_str.c_str( );
}
04 Feb, 2009, David Haley wrote in the 6th comment:
Votes: 0
Yes. And now you just have to be aware that if you call it with a bad flagarray, it'll probably crash (or do something very weird).

Remind me one of these days to write that little bit set class I mentioned that knows about its associated flag array.
04 Feb, 2009, Kayle wrote in the 7th comment:
Votes: 0
Of course. :P
0.0/7