24 Oct, 2011, arholly wrote in the 1st comment:
Votes: 0
Hello.
I've got a crash bug in my code I inherited and I'm not sure what it is doing. When I go to save a new poll/survey, it crashes, as in completely shuts down the mud. Now, I know how to run gdb to get information, but I'm not sure where to go next.
Loaded symbols for /lib/ld-linux.so.2
Core was generated by `grep do_log'.
Program terminated with signal 3, Quit.
#0 0x00d867f2 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2
(gdb) list
340 * Memory debugging if needed.
341 */
342 #if defined(MALLOC_DEBUG)
343 malloc_debug( 2 );
344 #endif
345
346 /*
347 * Init time.
348 */
349 gettimeofday( &now_time, NULL );
(gdb) bt
#0 0x00d867f2 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2
#1 0x00ed5ff3 in ?? ()
#2 0x00000001 in ?? ()
#3 0x08049edb in do_rp_ok (ch=0xa, argument=0x1000 <Address 0x1000 out of bounds>) at act_comm.c:2750
#4 0x0804ad24 in do_group (ch=0xa, argument=0x6 <Address 0x6 out of bounds>) at act_comm.c:2572
#5 0x0804c368 in do_quit (ch=0x0, argument=0x8057800 "") at act_comm.c:2205
#6 0x00e28e9c in ?? ()
#7 0x00da1ca0 in ?? () from /lib/ld-linux.so.2
#8 0x08057800 in do_nominate (ch=0x804b550, argument=0xda1ca0 "") at act_info.c:3854
#9 0x080497f1 in _start ()
(gdb) info args
No symbol table info available.
(gdb) frame 1
#1 0x00ed5ff3 in ?? ()
(gdb) fram 2
#2 0x00000001 in ?? ()
(gdb) frame 3
#3 0x08049edb in do_rp_ok (ch=0xa, argument=0x1000 <Address 0x1000 out of bounds>) at act_comm.c:2750
2750 free_string(ch->pcdata->rpok_string);
(gdb) frame 4
#4 0x0804ad24 in do_group (ch=0xa, argument=0x6 <Address 0x6 out of bounds>) at act_comm.c:2572
2572 sprintf( buf,
(gdb) frame 5
#5 0x0804c368 in do_quit (ch=0x0, argument=0x8057800 "") at act_comm.c:2205
2205 wiznet("$N rejoins the real world.",ch,NULL,WIZ_LOGINS,0,get_trust(ch));
(gdb) frame 6
#6 0x00e28e9c in ?? ()
(gdb) frame 7
#7 0x00da1ca0 in ?? () from /lib/ld-linux.so.2
(gdb) frame 8
#8 0x08057800 in do_nominate (ch=0x804b550, argument=0xda1ca0 "") at act_info.c:3854
3854 if(vote_tally[0][i].name == NULL
(gdb) frame 9
#9 0x080497f1 in _start ()

Can someone help me out and see what I need to do next? I would appreciate an explanation as well so I can learn from this.

Thanks,
Arholly
24 Oct, 2011, Vatiken wrote in the 2nd comment:
Votes: 0
Hard to say, it appears that you might be attempting to free a string that doesn't exist in the first place.
24 Oct, 2011, Runter wrote in the 3rd comment:
Votes: 0
There's only one thing that causes a true crash, and that's dereferencing bad memory.

if(vote_tally[0][i].name == NULL


So after we know that, we can assume that one of the indicies goes into rogue pointer land. My best guess is that it's the i value. If you do "p i" in gdb at that point it would tell you the value of i. So investigate, dust for prints, get eye witness testimony, stake out the likely suspects, and get a collar.
24 Oct, 2011, arholly wrote in the 4th comment:
Votes: 0
OK, I did p i and it gave me this, but I have no clue what it means.
(gdb) p i
$1 = 16154612

OK, after further review, I tracked down where in the code that it is doing that.
if(!str_prefix(argument, "mayor"))
{
for(i = 0; i < 6; i++)
{
if(vote_tally[0][i].name == NULL
|| !str_cmp(vote_tally[0][i].name, "None"))
{
vote_tally[0][i].name = str_dup(nominee->name);
vote_tally[0][i].votes = 1;
break;
}
}
}

Now, it repeats that for some other nominee positions, but mayor is at the list.
24 Oct, 2011, Runter wrote in the 5th comment:
Votes: 0
I dunno, I'm not a C expert, but it looks like that gdb readout is a little funky. Also, I don't see a reason why i would be out of the for bound there in that context.

Someone more experienced with C will probably read the gdb properly. :p
24 Oct, 2011, kiasyn wrote in the 6th comment:
Votes: 0
#4 0x0804ad24 in do_group (ch=0xa, argument=0x6 <Address 0x6 out of bounds>) at act_comm.c:2572
2572 sprintf( buf,
(gdb) frame 5

can you paste more lines around this area?
24 Oct, 2011, arholly wrote in the 7th comment:
Votes: 0
Sure can, here is the whole function:
void do_group( CHAR_DATA *ch, char *argument )
{
char buf[MAX_STRING_LENGTH];
char arg[MAX_INPUT_LENGTH];
CHAR_DATA *victim;

one_argument( argument, arg );

if ( arg[0] == '\0' )
{
CHAR_DATA *gch;
CHAR_DATA *leader;

leader = (ch->leader != NULL) ? ch->leader : ch;
sprintf( buf, "%s's group:\n\r", PERS(leader, ch) );
send_to_char( buf, ch );

for ( gch = char_list; gch != NULL; gch = gch->next )
{
if ( is_same_group( gch, ch ) )
{
sprintf( buf,
"[ %s ] %-16s %s %5d xp\n\r",
IS_NPC(gch) ? "Mob" : clan_table[gch->clan].who_name,
capitalize( PERS(gch, ch) ),
health_string(gch),
gch->exp );
send_to_char( buf, ch );
}
}
return;
}

if ( ( victim = get_char_room( ch, arg ) ) == NULL )
{
send_to_char( "They aren't here.\n\r", ch );
return;
}

if ( ch->master != NULL || ( ch->leader != NULL && ch->leader != ch ) )
{
send_to_char( "But you are following someone else!\n\r", ch );
return;
}

if ( victim->master != ch && ch != victim )
{
act_new("$N isn't following you.",ch,NULL,victim,TO_CHAR,P_SLEEP,1);
return;
}

if (IS_AFFECTED(victim,AFF_CHARM))
{
send_to_char("You can't remove charmed mobs from your group.\n\r",ch);
return;
}

if (IS_AFFECTED(ch,AFF_CHARM))
{
act_new("You like your master too much to leave $m!",
ch,NULL,victim,TO_VICT,P_SLEEP,1);
return;
}

if ( is_same_group( victim, ch ) && ch != victim )
{
victim->leader = NULL;
act_new("$n removes $N from $s group.",
ch,NULL,victim,TO_NOTVICT,P_REST,1);
act_new("$n removes you from $s group.",
ch,NULL,victim,TO_VICT,P_SLEEP,1);
act_new("You remove $N from your group.",
ch,NULL,victim,TO_CHAR,P_SLEEP,1);
return;
}

victim->leader = ch;
act_new("$N joins $n's group.",ch,NULL,victim,TO_NOTVICT,P_REST,1);
act_new("You join $n's group.",ch,NULL,victim,TO_VICT,P_SLEEP,1);
act_new("$N joins your group.",ch,NULL,victim,TO_CHAR,P_SLEEP,1);
return;
}

Or, if you just want what list shows,
2567
2568 for ( gch = char_list; gch != NULL; gch = gch->next )
2569 {
2570 if ( is_same_group( gch, ch ) )
2571 {
2572 sprintf( buf,
2573 "[ %s ] %-16s %s %5d xp\n\r",
2574 IS_NPC(gch) ? "Mob" : clan_table[gch->clan].who_name,
2575 capitalize( PERS(gch, ch) ),
2576 health_string(gch),
25 Oct, 2011, Davion wrote in the 8th comment:
Votes: 0
I think something is happening in your nominate function. Looking at this

#3  0x08049edb in do_rp_ok (ch=0xa, argument=0x1000 <Address 0x1000 out of bounds>) at act_comm.c:2750
#4 0x0804ad24 in do_group (ch=0xa, argument=0x6 <Address 0x6 out of bounds>) at act_comm.c:2572
#5 0x0804c368 in do_quit (ch=0x0, argument=0x8057800 "") at act_comm.c:2205
#6 0x00e28e9c in ?? ()
#7 0x00da1ca0 in ?? () from /lib/ld-linux.so.2
#8 0x08057800 in do_nominate (ch=0x804b550, argument=0xda1ca0 "") at act_info.c:3854


It looks like do_nominate() somehow calls do_quit(). When do_quit is called, ch is 0x0 (NULL) this is bad juujuu. The next few frames, ch is random garbage (0xa) which is also bad juujuu. Wanna show us your nominate function, specifically where it might send something to do_quit().
25 Oct, 2011, arholly wrote in the 9th comment:
Votes: 0
Ok, this is the do_nominate function.
void do_nominate(CHAR_DATA *ch, char *argument)
{
CHAR_DATA *nominee;
char arg[MAX_INPUT_LENGTH];
bool online = FALSE;
bool in_char_list = FALSE;
int i;

argument = one_argument(argument, arg);
if(argument[0] == '\0' || arg[0] == '\0')
{
send_to_char("Nominate whom for which position?\n\r", ch);
return;
}

if(ch->pcdata->last_vote > current_time - 24*60*60 && !IS_ADMIN(ch))
{
send_to_char("Only one vote per 24 hours.\n\r", ch);
return;
}

if(is_online(arg)) online = TRUE;
if(pc_in_char_list(arg)) in_char_list = TRUE;

if((nominee = get_player(arg)) == NULL)
{
send_to_char("No such person.\n\r", ch);
return;
}

if(nominee->race != race_lookup("human"))
{
send_to_char("Only the mortal should be in the public eye.\n\r", ch);
return;
}

if(is_nominee(nominee, 0))
{
send_to_char("They're already nominated to be mayor!\n\r", ch);
return;
}
else if(is_nominee(nominee, 1))
{
send_to_char("They're already nominated to be an alderman!\n\r", ch);
return;
}
else if(is_nominee(nominee, 2))
{
send_to_char("They're already nominated to be a judge!\n\r", ch);
return;
}

if(!str_prefix(argument, "mayor"))
{
for(i = 0; i < 6; i++)
{
if(vote_tally[0][i].name == NULL
|| !str_cmp(vote_tally[0][i].name, "None"))
{
vote_tally[0][i].name = str_dup(nominee->name);
vote_tally[0][i].votes = 1;
break;
}
}
}
else if(!str_prefix(argument, "alderman"))
{
for(i = 0; i < 6; i++)
{
if(vote_tally[1][i].name == NULL
|| !str_cmp(vote_tally[0][i].name, "None"))
{
vote_tally[1][i].name = str_dup(nominee->name);
vote_tally[1][i].votes = 1;
break;
}
}
}
else if(!str_prefix(argument, "judge"))
{
for(i = 0; i < 6; i++)
{
if(vote_tally[2][i].name == NULL
|| !str_cmp(vote_tally[0][i].name, "None"))
{
vote_tally[2][i].name = str_dup(nominee->name);
vote_tally[2][i].votes = 1;
break;
}
}
}
else
{
send_to_char("Positions available are: judge, alderman, mayor.\n\r", ch);
return;
}

ch->pcdata->last_vote = current_time;
fwrite_votes();
send_to_char("Nomination submitted.\n\r", ch);

if(!online && !in_char_list)
{
free_char(nominee);
}
}


And just for reference, here is do_quit. When I am looking at it in eclipse, it is telling me that some NULL's could not be resolved.
void do_quit( CHAR_DATA *ch, char *argument )
{
DESCRIPTOR_DATA *d,*d_next;
int id;

if ( IS_NPC(ch) )
return;

if ( ch->position == P_FIGHT )
{
send_to_char( "No way! You are fighting.\n\r", ch );
return;
}

if ( ch->position < P_STUN )
{
send_to_char( "You're not DEAD yet.\n\r", ch );
return;
}

send_to_char("Parting is such sweet sorrow.\n\r",ch);
act( "$n has left the game.", ch, NULL, NULL, TO_ROOM, 0 );
sprintf( log_buf, "%s has quit.", ch->name );
log_string( log_buf );
wiznet("$N rejoins the real world.",ch,NULL,WIZ_LOGINS,0,get_trust(ch));

/* Added RSS feed information */
sprintf( log_buf, "%s has logged out.", ch->name );
log_to_file(logfile, GLOBAL_XML_IN, log_buf);


/*
* Ditch buildermode mobs and objects.
*/
if(IS_SET(ch->comm, COMM_BUILDER))
{
cleanse_builder_stuff(ch);
REMOVE_BIT(ch->comm, COMM_BUILDER);
}

/*
* After extract_char the ch is no longer valid!
*/
save_char_obj( ch );
id = ch->id;
d = ch->desc;
extract_char( ch, TRUE );
if ( d != NULL )
close_socket( d );

/* toast evil cheating bastards */
for (d = descriptor_list; d != NULL; d = d_next)
{
CHAR_DATA *tch;

d_next = d->next;
tch = d->original ? d->original : d->character;
if (tch && tch->id == id)
{
extract_char(tch,TRUE);
close_socket(d);
}
}

return;
}
25 Oct, 2011, Vatiken wrote in the 10th comment:
Votes: 0
wiznet("$N rejoins the real world.",ch,NULL,WIZ_LOGINS,0,get_trust(ch));

Change $N to $n…

He shoots, he scores!!!
25 Oct, 2011, arholly wrote in the 11th comment:
Votes: 0
Sorry, still goes boom.
25 Oct, 2011, Vatiken wrote in the 12th comment:
Votes: 0
Really? Damn. Do_group() and do_rp_ok() are next functions I'd have to see then.
25 Oct, 2011, arholly wrote in the 13th comment:
Votes: 0
Do group is post 7.
Do_rp_ok is:
void do_rp_ok(CHAR_DATA *ch, char *argument)
{
char buf[MAX_STRING_LENGTH];

if(IS_NPC(ch))
{
return;
}

if(IS_SET(ch->plr_flags, PLR_RP_OK))
{
send_to_char("People will no longer be able to join you for RP.\n\r",
ch);
REMOVE_BIT(ch->plr_flags, PLR_RP_OK);
free_string(ch->pcdata->rpok_string);
ch->pcdata->rpok_string = str_dup("None");
return;
}
else
{
send_to_char("You can now be joined by others for RP.\n\r", ch);
SET_BIT(ch->plr_flags, PLR_RP_OK);
if(argument[0] != '\0')
{
sprintf(buf, "Your RP title has been set to: %s\n\r", argument);
send_to_char(buf, ch);
free_string(ch->pcdata->rpok_string);
ch->pcdata->rpok_string = str_dup(argument);
}
}
}
25 Oct, 2011, Davion wrote in the 14th comment:
Votes: 0
Ok, so from do_nominate, it's probably calling quit from this chunk of code

if(!online && !in_char_list)
{
free_char(nominee);
}


which leads me to believe that get_player() would create a player object even if the person is offline. scary stuff and not stock rom.
25 Oct, 2011, arholly wrote in the 15th comment:
Votes: 0
OK, well, let's see. I don't see anything that would prohibit it from getting a player that is not online.
CHAR_DATA *get_player( char *argument )
{
CHAR_DATA *ch;

for ( ch = char_list; ch; ch = ch->next )
{
if ( IS_NPC( ch ) )
continue;
if ( is_name( argument, ch->name ) )
return ch;
}

return get_player_file( argument );
}


I know what the nominate code wants to do, it wants to make sure the player is really a player before nominating them. Is there a better way to do that? This makes me feel like I am out of my league here.

Arholly
0.0/15