21 Sep, 2012, arholly wrote in the 1st comment:
Votes: 0
Hi there:
I'm busy taking out some old color code in favor of using KaVir's protocol color. So, this is what I did. I replaced the send_to_char that we had and replaced it with a stock rom send_to_char. It worked OK, but I noticed a few problems, but nothing I don't think I can figure out. For one, when I did things like do_score, it didn't return a prompt to me.

However, the real problem is that when I went to shutdown my mud, it finally started to shutdown properly (something it hadn't done for a LONG time), but I got this (warning: It's long). I'm including the color code for send_to_char I'd been using and the stock one I am currently using. Unfortunately, I have no clue what it means.

GDB shutdown said:
Cleaning knowledge list
Cleaning news list
Cleaning out index hashes.
Cleaning out area list
cleaning out remaining shop data
cleaning out social table.
cleaning out plots
Cleaning out events / scripts / actors
*** glibc detected *** /home/m243bra/ptdev/src/project: double free or corruption (top): 0x08353b80 ***
======= Backtrace: =========
/lib/libc.so.6[0xb064a5]
/lib/libc.so.6(cfree+0x59)[0xb068e9]
/home/m243bra/ptdev/src/project[0x80f1721]
/home/m243bra/ptdev/src/project[0x80a6145]
/home/m243bra/ptdev/src/project[0x809229f]
/home/m243bra/ptdev/src/project[0x80924e3]
/lib/libc.so.6(__libc_start_main+0xdc)[0xab2e9c]
/home/m243bra/ptdev/src/project[0x8049151]
======= Memory map: ========
002b1000-002bb000 r-xp 00000000 fd:01 56263788 /lib/libnss_files-2.5.so
002bb000-002bc000 r–p 00009000 fd:01 56263788 /lib/libnss_files-2.5.so
002bc000-002bd000 rw-p 0000a000 fd:01 56263788 /lib/libnss_files-2.5.so
00a7e000-00a99000 r-xp 00000000 fd:01 56262898 /lib/ld-2.5.so
00a99000-00a9a000 r–p 0001a000 fd:01 56262898 /lib/ld-2.5.so
00a9a000-00a9b000 rw-p 0001b000 fd:01 56262898 /lib/ld-2.5.so
00a9d000-00bf1000 r-xp 00000000 fd:01 56263398 /lib/libc-2.5.so
00bf1000-00bf2000 —p 00154000 fd:01 56263398 /lib/libc-2.5.so
00bf2000-00bf4000 r–p 00154000 fd:01 56263398 /lib/libc-2.5.so
00bf4000-00bf5000 rw-p 00156000 fd:01 56263398 /lib/libc-2.5.so
00bf5000-00bf8000 rw-p 00bf5000 00:00 0
00bfa000-00c21000 r-xp 00000000 fd:01 56263557 /lib/libm-2.5.so
00c21000-00c22000 r–p 00026000 fd:01 56263557 /lib/libm-2.5.so
00c22000-00c23000 rw-p 00027000 fd:01 56263557 /lib/libm-2.5.so
00cfe000-00d09000 r-xp 00000000 fd:01 56263576 /lib/libgcc_s-4.1.2-20080825.so.1
00d09000-00d0a000 rw-p 0000a000 fd:01 56263576 /lib/libgcc_s-4.1.2-20080825.so.1
00d3d000-00d4e000 r-xp 00000000 fd:01 56263596 /lib/libresolv-2.5.so
00d4e000-00d4f000 r–p 00010000 fd:01 56263596 /lib/libresolv-2.5.so
00d4f000-00d50000 rw-p 00011000 fd:01 56263596 /lib/libresolv-2.5.so
00d50000-00d52000 rw-p 00d50000 00:00 0
00fb0000-00fb1000 r-xp 00fb0000 00:00 0 [vdso]
00fcc000-00fd0000 r-xp 00000000 fd:01 56263593 /lib/libnss_dns-2.5.so
00fd0000-00fd1000 r–p 00003000 fd:01 56263593 /lib/libnss_dns-2.5.so
00fd1000-00fd2000 rw-p 00004000 fd:01 56263593 /lib/libnss_dns-2.5.so
08048000-08156000 r-xp 00000000 fd:01 69140600 /home/m243bra/ptdev/src/project
08156000-08157000 rw-p 0010d000 fd:01 69140600 /home/m243bra/ptdev/src/project
08157000-08374000 rw-p 08157000 00:00 0 [heap]
b7ff5000-b7ff7000 rw-p b7ff5000 00:00 0
b7ffc000-b7ffd000 rw-p b7ffc000 00:00 0
bffe9000-bfffe000 rw-p bffe8000 00:00 0 [stack]

Program received signal SIGABRT, Aborted.
0x00a7e7f2 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2
(gdb) bt
#0 0x00a7e7f2 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2
#1 0x00ac5df0 in raise () from /lib/libc.so.6
#2 0x00ac7701 in abort () from /lib/libc.so.6
#3 0x00afe18b in __libc_message () from /lib/libc.so.6
#4 0x00b064a5 in _int_free () from /lib/libc.so.6
#5 0x00b068e9 in free () from /lib/libc.so.6
#6 0x080f1721 in free_char (ch=0x8353b80) at recycle.c:969
#7 0x080a6145 in purgeExtractedWorldData () at handler.c:4716
#8 0x0809229f in cleanup_mud (control=8) at comm.c:584
#9 0x080924e3 in main (argc=Cannot access memory at address 0x55c8
) at comm.c:660
(gdb) frame 0
#0 0x00a7e7f2 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2
(gdb) list
589 int main( int argc, char **argv )
590 {
591 struct timeval now_time;
592
593 bool fCopyOver = FALSE;
594
595 /*
596 * Init time.
597 */
598 gettimeofday( &now_time, NULL );
(gdb) info locals
No symbol table info available.
(gdb) frame 1
#1 0x00ac5df0 in raise () from /lib/libc.so.6
(gdb) list
599 current_time = (time_t) now_time.tv_sec;
600 strncpy( str_boot_time, ctime( &current_time ), sizeof(str_boot_time));
601
602 /*
603 * Reserve one channel for our use.
604 */
605 if ( ( fpReserve = fopen( NULL_FILE, "r" ) ) == NULL )
606 {
607 perror( NULL_FILE );
608 exit( 1 );
(gdb) info locals
No symbol table info available.
(gdb) frame 3
#3 0x00afe18b in __libc_message () from /lib/libc.so.6
(gdb) list
609 }
610
611 /*
612 * Get the port number and initial log file number.
613 */
614 port = MUD_PORT;
615 if ( argc > 1 )
616 {
617 if ( !is_number( argv[1] ) )
618 {
(gdb) info local
No symbol table info available.
(gdb) frame 2
#2 0x00ac7701 in abort () from /lib/libc.so.6
(gdb) list
619 fprintf( stderr, "Usage: %s [port #] [first log #]\n", argv[0] );
620 exit( 1 );
621 }
622 else if ( ( port = atoi( argv[1] ) ) <= 1024 )
623 {
624 fprintf( stderr, "Port number must be above 1024.\n" );
625 exit( 1 );
626 }
627
628 /* Are we recovering from a copyover? */
(gdb) info local
No symbol table info available.
(gdb) frame 4
#4 0x00b064a5 in _int_free () from /lib/libc.so.6
(gdb) list
629 if (argv[3] && argv[3][0])
630 {
631 fCopyOver = TRUE;
632 control = atoi(argv[3]);
633 }
634 else
635 fCopyOver = FALSE;
636 }
637
638 if( argv[2] == NULL || !is_number( argv[2] ) )
(gdb) info local
No symbol table info available.
(gdb) frame 5
#5 0x00b068e9 in free () from /lib/libc.so.6
(gdb) list
639 snprintf(logfile, sizeof(logfile), "%d", 1000);
640 else
641 snprintf(logfile, sizeof(logfile), "%s", argv[2] );
642
643 /*
644 * Run the game.
645 */
646 // if (!fCopyOver)
647 control = init_socket( port );
648
(gdb) info local
No symbol table info available.
(gdb) frame 6
#6 0x080f1721 in free_char (ch=0x8353b80) at recycle.c:969
969 PURGE_DATA(ch);
(gdb) list
964 {
965 ed_next = ed->next;
966 free_extra_descr(ed);
967 }
968 ch->extra_descr = NULL;
969 PURGE_DATA(ch);
970 return;
971 }
972
973
(gdb) info local
obj = <value optimized out>
obj_next = 0x8353b80
paf = <value optimized out>
paf_next = 0x8353b80
ed = 0x0
ed_next = 0x8353b80
__FUNCTION__ = "free_char"
(gdb) frame 7
#7 0x080a6145 in purgeExtractedWorldData () at handler.c:4716
4716 free_char(ch);
(gdb) list
4711
4712 for(ch = worldExtractedCharacters; ch; ch = ch_next)
4713 {
4714 ch_next = ch->next;
4715 UNLINK_SINGLE(ch, next, CHAR_DATA, worldExtractedCharacters);
4716 free_char(ch);
4717 }
4718 for(obj = worldExtractedObjects; obj; obj = obj_next)
4719 {
4720 obj_next = obj->next;
(gdb) info local
ch = 0x8353b80
ch_next = 0x0
obj = <value optimized out>
obj_next = <value optimized out>
(gdb) frame 8
#8 0x0809229f in cleanup_mud (control=8) at comm.c:584
584 purgeExtractedWorldData();
(gdb) list
579 pEvent_next = pEvent->next;
580
581 free_event(pEvent);
582 }
583
584 purgeExtractedWorldData();
585 log_string("Project Twilight has completed its cleanup procedure and may now shutdown.");
586 return;
587 }
588
(gdb) info local
mob_index = <value optimized out>
room_index = 0x0
obj_index = <value optimized out>
pShop = <value optimized out>
pShop_next = 0x0
pArea = <value optimized out>
pArea_next = 0x0
ch = <value optimized out>
ch_next = <value optimized out>
obj = <value optimized out>
obj_next = <value optimized out>
pack = <value optimized out>
pack_next = <value optimized out>
org = <value optimized out>
org_next = <value optimized out>
stock = <value optimized out>
stock_next = <value optimized out>
paper = <value optimized out>
paper_next = <value optimized out>
d = <value optimized out>
d_next = <value optimized out>
pbg = <value optimized out>
pbg_next = <value optimized out>
pnote = <value optimized out>
pnote_next = <value optimized out>
help = <value optimized out>
help_next = <value optimized out>
pPlot = <value optimized out>
pPlot_next = 0x0
pEvent = 0x0
pEvent_next = 0x0
iHash = 1024
(gdb) frame 9
#9 0x080924e3 in main (argc=Cannot access memory at address 0x55c8
) at comm.c:660
660 cleanup_mud(control);
(gdb) list
655 copyover_recover();
656 */
657 game_loop_unix( control );
658 /* shutdown_web(); */
659
660 cleanup_mud(control);
661
662
663 /*
664 * That's all, folks.
(gdb) info local
now_time = {tv_sec = 1348241263, tv_usec = 346214}


/*
* Write to one char, new colour version, by Lope.
*/
/*void send_to_char( const char *txt, CHAR_DATA *ch )
{
const char *point;
char *point2;
char buf[ MSL*4 ]={'\0'};
int skip = 0;

buf[0] = '\0';
point2 = buf;

if( ch->desc && ch->condition[COND_TRIPPING] > 60 )
{
random_colours((char *)txt);
}

if( txt && ch->desc )
{
if( IS_SET( ch->plr_flags, PLR_COLOUR ) )
{
for( point = txt ; *point ; point++ )
{
if( *point == '{' )
{
point++;
skip = colour( *point, ch, point2 );
while( skip– > 0 )
++point2;
continue;
}
*point2 = *point;
*++point2 = '\0';
}
*point2 = '\0';
if( ch->desc != NULL )
write_to_buffer( ch->desc, buf, point2 - buf );
else
trigger_test(buf, ch, NULL);
}
else
{
for( point = txt ; *point ; point++ )
{
if( *point == '{' )
{
point++;
continue;
}
*point2 = *point;
*++point2 = '\0';
}
*point2 = '\0';
if( ch->desc != NULL )
write_to_buffer( ch->desc, buf, point2 - buf );
else
trigger_test(buf, ch, NULL);
}
}
return;
}*/

/*
* Write to one char from stock ROM
*/
void send_to_char( const char *txt, CHAR_DATA *ch )
{
if ( txt != NULL && ch->desc != NULL )
write_to_buffer( ch->desc, txt, strlen(txt) );
return;
}
21 Sep, 2012, arholly wrote in the 2nd comment:
Votes: 0
Ok, I finally figured out how to run Valgrind and got this from it. But I am not really sure where to go from there. I figured this might help if anyone knows anything.
22 Sep, 2012, Rarva.Riendf wrote in the 3rd comment:
Votes: 0
When detecting error with Valgrind, (like write or read error) first thing to do is to fix the first error that appears, as fixing it can remove a lot of the following one.
and relaunch it till there is no error left.
As muds are quite small it is also easy to retest them after each errors fixed. So no need to try to go fix errors in multiple place at once as a lot of memory error can be triggered in some seemingly unrelated places in the code.

as en example
==15706== Invalid read of size 4
==15706== at 0x8108805: aggr_update (update.c:1479)
==15706== by 0x810B5DD: update_handler (update.c:1683)
==15706== by 0x8091C16: game_loop_unix (comm.c:1058)
==15706== by 0x80924D5: main (comm.c:657)
==15706== Address 0x43f3150 is 0 bytes inside a block of size 1,844 free'd
==15706== at 0x400579D: free (vg_replace_malloc.c:325)
==15706== by 0x80F1720: free_char (recycle.c:969)
==15706== by 0x8089163: close_socket (comm.c:1283)
==15706== by 0x8080004: do_shutdown (act_wiz.c:1761)
==15706== by 0x80AE8F6: interpret (interp.c:976)
==15706== by 0x808806A: substitute_alias (alias.c:64)
==15706== by 0x8091BEE: game_loop_unix (comm.c:1038)

>==15706== Invalid read of size 4
>Address 0x43f3150 is 0 bytes inside a block of size 1,844 free'd

Means you tried to read the memory in a place where it has been freed.

Basically the value you just read is something you should treat as random garbage (though if it is not overwritten it probably is still valid)
Most random problems come from those. As they can then occur at any other random place where this value is used.

Valgrind tells that your mud: is leaking memory, may crash at random, and has potential random behaviour.
When you have no error left it will not means it is bug free, but at least a little easier to debug.
23 Sep, 2012, arholly wrote in the 4th comment:
Votes: 0
So, I am not sure then where to start. Do start with aggr_update or free_char? Both look to be a problem, but I'm not sure if I am reading that right.
23 Sep, 2012, Elgatodefuego wrote in the 5th comment:
Votes: 0
I've not used Valgrind in some time, but the first error I saw from that extensive log was..

==15706== Invalid write of size 1
==15706== at 0x8091BFD: game_loop_unix (comm.c:1049)

That seems to me that comm.c is trying to make a call to an invalid memory space. I know some codebases will try to write to a log file, send a Wiznet message, or other global message when trying to do a shut down. Just my 2 cents.
23 Sep, 2012, Rarva.Riendf wrote in the 6th comment:
Votes: 0
==15706== Invalid read of size 4
==15706== at 0x8108805: aggr_update (update.c:1479) <- you tried to read a value in a space that was freed, the real question is why do you try to read a value when you are not even sure it still exists.
==15706== by 0x810B5DD: update_handler (update.c:1683)
==15706== by 0x8091C16: game_loop_unix (comm.c:1058)
==15706== by 0x80924D5: main (comm.c:657)
==15706== Address 0x43f3150 is 0 bytes inside a block of size 1,844 free'd
==15706== at 0x400579D: free (vg_replace_malloc.c:325)
==15706== by 0x80F1720: free_char (recycle.c:969) <- the variable has been freed here. There is no problem with that. The problem is that after that you still try to access it afterwards. I would put a breakpoint in
aggrupdate at line 1479 and look at the value that you are reading.
==15706== by 0x8089163: close_socket (comm.c:1283)
==15706== by 0x8080004: do_shutdown (act_wiz.c:1761)
==15706== by 0x80AE8F6: interpret (interp.c:976)
==15706== by 0x808806A: substitute_alias (alias.c:64)
==15706== by 0x8091BEE: game_loop_unix (comm.c:1038)

sidenote: I never could understand how the memory management of ROM worked so I rewrited it entirely. So I cannot really help you past that.
23 Sep, 2012, Oliver wrote in the 7th comment:
Votes: 0
Rarva.Riendf said:
sidenote: I never could understand how the memory management of ROM worked so I rewrited it entirely. So I cannot really help you past that.


The memory management of RoM…? It just allocates memory, and instead of freeing the memory directly (to avoid problems like the one in this thread), it just clears/frees the object's variables and puts it in a "used" stack. If the "used" stack is not empty when the memory-allocation function is called, then it re-purposes the top object from the "used" stack as the new object. It's a memory recycling system. The objects that use this system have an IS_VALID flag to prevent accidental accessing of improperly-freed blocks.
23 Sep, 2012, Davion wrote in the 8th comment:
Votes: 0
Wanna paste your new_char() function and free_char() function? also PURGE_DATA(). Some of your warnings may simply be a structure not initialized properly. Would like to rule that out.
24 Sep, 2012, arholly wrote in the 9th comment:
Votes: 0
Sure, here they are:
void free_char (CHAR_DATA *ch)
{
OBJ_DATA *obj;
OBJ_DATA *obj_next;
AFFECT_DATA *paf;
AFFECT_DATA *paf_next;
EXTRA_DESCR_DATA *ed, *ed_next;

Escape(ch);

if (IS_NPC(ch))
mobile_count–;

for (obj = ch->carrying; obj != NULL; obj = obj_next)
{
obj_next = obj->next_content;
extract_obj(obj);
}

for (paf = ch->affected; paf != NULL; paf = paf_next)
{
paf_next = paf->next;
affect_remove(ch,paf);
}

if(ch->script != NULL)
free_script(ch->script);

PURGE_DATA(ch->aifile);
PURGE_DATA(ch->alt_description);
PURGE_DATA(ch->alt_long_descr);
PURGE_DATA(ch->alt_name);
PURGE_DATA(ch->colours[0]);
PURGE_DATA(ch->colours[1]);
PURGE_DATA(ch->demeanor);
PURGE_DATA(ch->description);
PURGE_DATA(ch->email_addr);
PURGE_DATA(ch->ghouled_by);
PURGE_DATA(ch->ignore);
PURGE_DATA(ch->laston);
PURGE_DATA(ch->long_descr);
PURGE_DATA(ch->married);
PURGE_DATA(ch->material);
PURGE_DATA(ch->name);
PURGE_DATA(ch->nature);
PURGE_DATA(ch->next_in_room);
PURGE_DATA(ch->oldname);
PURGE_DATA(ch->pack);
PURGE_DATA(ch->prefix);
PURGE_DATA(ch->profession);
PURGE_DATA(ch->prompt);
PURGE_DATA(ch->reply);
PURGE_DATA(ch->short_descr);
PURGE_DATA(ch->sire);
PURGE_DATA(ch->surname);
PURGE_DATA(ch->switch_desc);
PURGE_DATA(ch->to_learn);
PURGE_DATA(ch->pnote);
PURGE_DATA(ch->pcdata);

for (ed = ch->extra_descr; ed != NULL; ed = ed_next )
{
ed_next = ed->next;
free_extra_descr(ed);
}
ch->extra_descr = NULL;
PURGE_DATA(ch);
return;
}

CHAR_DATA *new_char (void)
{
CHAR_DATA *ch;
int i;

ALLOC_DATA(ch, CHAR_DATA, 1);

ch->hunted = FALSE;

ch->aifile = NULL;
ch->alt_description = NULL;
ch->alt_long_descr = NULL;
ch->alt_name = NULL;
ch->demeanor = NULL;
ch->description = NULL;
ch->email_addr = NULL;
ch->ghouled_by = NULL;
ch->ignore = NULL;
ch->laston = NULL;
ch->long_descr = NULL;
ch->married = NULL;
ch->material = NULL;
ch->name = NULL;
ch->nature = NULL;
ch->next_in_room = NULL;
ch->oldname = NULL;
ch->pack = NULL;
ch->prefix = NULL;
ch->profession = NULL;
ch->prompt = NULL;
ch->reply = NULL;
ch->short_descr = NULL;
ch->sire = NULL;
ch->surname = NULL;
ch->switch_desc = NULL;
ch->to_learn = NULL;

ch->BUILDER_MODE = 0;
ch->act = 0;
ch->act2 = 0;
ch->act_points = 0;
ch->affected_by = 0;
ch->affected_by2 = 0;
ch->agghealth = 7;
ch->attitude = 0;
ch->balance = 0;
ch->bank_account = 0;
ch->bg_count = 0;
ch->cents = 0;
ch->char_age = 0;
ch->clan = 0;
ch->combo_success = 0;
ch->comm = 0;
ch->concede = 0;
ch->current_tip = 0;
ch->dollars = 0;
ch->email_lock = 0;
ch->employer = 0;
ch->exp = 0;
ch->falldam = 0;
ch->form = 0;
ch->gen = 0;
ch->health = 7;
ch->herd_timer = 0;
ch->home = 0;
ch->hunter_vis = 0;
ch->id = 0;
ch->imm_flags = 0;
ch->jump_timer = 0;
ch->lines = PAGELEN;
ch->logon = current_time;
ch->markup = 0;
ch->max_traits[0] = 5;
ch->max_traits[1] = 5;
ch->off_flags = 0;
ch->on_phone = 0;
ch->ooc_xp_count = 0;
ch->ooc_xp_time = 0;
ch->oocxp = 0;
ch->parts = 0;
ch->played = 0;
ch->plr_flags = 0;
ch->position = P_STAND;
ch->pospts = 0;
ch->res_flags = 0;
ch->ritepoint = 0;
ch->stock_ticker = 0;
ch->version = 0;
ch->vuln_flags = 0;
ch->wait = 0;
ch->warrants = 0;
ch->wiznet = 0;
ch->xp_job_acts = 0;
ch->xpgift = 0;
ch->GHB = 0;
ch->RBPG = 0;
ch->auspice = 0;
ch->bg_timer = 0;
ch->blood_timer = 0;
ch->breed = 0;
ch->carry_number = 0;
ch->carry_weight = 0;
ch->combat_flag = 0;
ch->dam_type = 0;
ch->daze = 0;
ch->default_pos = P_STAND;
ch->dice_mod = 0;
ch->diff_mod = 0;
ch->group = 0;
ch->incog_level = 0;
ch->infl_timer = 0;
ch->invis_level = 0;
ch->jump_dir = 0;
ch->max_GHB = 0;
ch->max_RBPG = 0;
ch->max_willpower = 0;
ch->mprog_delay = 0;
ch->power_timer = 0;
ch->race = 0;
ch->saving_throw = 0;
ch->sex = 0;
ch->shape = 0;
ch->size = 0;
ch->start_pos = P_STAND;
ch->timer = 0;
ch->torpor_timer = 0;
ch->train_success = 0;
ch->willpower = 0;
ch->trust = 0;

for (i = 0; i < 3; i++)
ch->armor[i] = 100;
for (i = 0; i < 3; i++)
ch->clan_powers[i] = -1;
for (i = 0; i < 3; i++)
ch->colours[i] = NULL;
for (i = 0; i < MAX_STATS; i ++)
{
ch->perm_stat[i] = 1;
ch->mod_stat[i] = 0;
}
clear_rite(ch);

return ch;
}

#define PURGE_DATA(data) \
do { \
if(data) \
{ \
free((void *)data); \
} \
else { \
if(logFail) { \
log_string((char *)Format("clear_free_lists: unable to purge_data as it was NULL from: %s %s %d", __FILE__, __FUNCTION__, __LINE__)); \
} \
} \
data = NULL; \
} while(0)
24 Sep, 2012, Davion wrote in the 10th comment:
Votes: 0
k. Show aggr_update (). Please mark off which line is 1479 :)
24 Sep, 2012, arholly wrote in the 11th comment:
Votes: 0
Line 12 in the box is line 1479.

void aggr_update( void )
{
CHAR_DATA *wch, *wch_next;
CHAR_DATA *ch, *ch_next;
CHAR_DATA *vch, *vch_next;
CHAR_DATA *victim, *prev;

// say WHA? (Zeroed! by Omega)
wch = wch_next = ch = ch_next = vch = vch_next = victim = prev = NULL;
for ( wch = char_list; wch != NULL; wch = wch_next )
{
wch_next = wch->next; //<—-LINE 1479
if ( IS_NPC(wch)
|| wch->trust >= LEVEL_IMMORTAL
|| wch->in_room == NULL
|| wch->in_room->area->empty
|| IS_SET(wch->act, ACT_REINCARNATE)) {
prev = wch;
continue;
}
for ( ch = wch->in_room->people; ch != NULL; ch = ch_next )
{
int count;
ch_next = ch->next_in_room;
if ( (!IS_NPC(ch)
&& !IS_SET(ch->act2, ACT2_FRENZY))
|| !IS_SET(ch->act, ACT_AGGRESSIVE)
|| ch->fighting != NULL
|| IS_AFFECTED(ch, AFF_CHARM)
|| !IS_AWAKE(ch)
|| ( IS_SET(ch->act, ACT_WIMPY) && IS_AWAKE(wch) )
|| !can_see( ch, wch )
|| number_bits(1) == 0)
prev = wch;
continue;
/*
* Ok we have a 'wch' player character and a 'ch' npc aggressor.
* Now make the aggressor fight a RANDOM pc victim in the room,
* giving each 'vch' an equal chance of selection.
*/
count = 0;
victim = NULL;
for ( vch = wch->in_room->people; vch != NULL; vch = vch_next )
{
vch_next = vch->next_in_room;
if ( (!IS_NPC(vch)
|| !IS_NPC(ch))
&& vch->trust < LEVEL_IMMORTAL
&& ( !IS_SET(ch->act, ACT_WIMPY) || !IS_AWAKE(vch) )
&& can_see( ch, vch ) )
{
if ( number_range( 0, count ) == 0 )
victim = vch;
count++;
}
}
if ( victim == NULL || IS_SET(victim->act2, ACT2_RP_ING)) {
prev = wch;
continue;
}
if(IS_NPC(ch) || ch->condition[COND_FEAR] < ch->condition[COND_ANGER])
multi_hit( ch, victim, TYPE_UNDEFINED );
else
do_function(ch, &do_flee, "" );
}
prev = wch;
}
return;
}
24 Sep, 2012, Davion wrote in the 12th comment:
Votes: 0
It looks like purgeExtractedWorldData() is a sweeper of sorts. It comes most likely at the end of a game loop and removes people who have been extracted. You're probably calling free_char() somewhere outside of this function which could cause problems. You're probably looking for something like… ExtractCharacter() instead of free_char.

The reason this is a problem for you, is your stock memory management has been ripped out and things are actually free()'d now. I'd strongly suggest adding a ch->next=NULL; somewhere in new_char() just in case ;).
24 Sep, 2012, Davion wrote in the 13th comment:
Votes: 0
PURGE_DATA(ch->next_in_room);


This may also be a problem ;). You do not want to call free() on the next person in the room. Any sort of list iterator you have, you'll want to simply NULL. So change that too
ch->next_in_room = NULL;


Terrifying.

:surprised:

You may want to go through this some more and look at what is pointing to what :)

PURGE_DATA(ch->ghouled_by);

pretty sure you're going to mess up anyone who someone is "ghouling" when they log off. PURGE_DATA should only be used on variables which have memory allocated specifically for that person. Any other that is simply used to point in reference to other things (ch->leader, ch->next, ch->next_in_room, most likely ch->ghouled_by) should be NULL'd or left out entirely.

…here's another particularly terrifying one :)

PURGE_DATA(ch->reply);


This means that if you send a tell to someone, when they log off, you're freed. That's scary stuff. Surprised you have an uptime with these butcher jobs on the game lists!
24 Sep, 2012, arholly wrote in the 14th comment:
Votes: 0
Thanks. That did it. Well, it is now giving an error someplace else I need to go and take a look at. It doesn't make sense why it is pushing there, but it is obviously a stack overflow since it is <value optimized out>. If I cannot figure it out, I will post here.
24 Sep, 2012, Davion wrote in the 15th comment:
Votes: 0
Heh, usually what the valgrind spits at us :). That may also be because you're running a high level of optimization. Look in your makefile for -O2, -O3 or somethin and just remove it for debugging. I'd leave it in on the live server tho. If they're one in the same, just turn it off to see if it will actually give you the value (may not still, but its always worth a shot)
24 Sep, 2012, arholly wrote in the 16th comment:
Votes: 0
Hmmm…OK, went and changed ch-reply to NULL, and am getting the same segfault.
GDB said:
Program received signal SIGSEGV, Segmentation fault.
aggr_update () at update.c:1479
1479 wch_next = wch->next;
(gdb) bt
#0 aggr_update () at update.c:1479
#1 0x0810b47e in update_handler () at update.c:1683
#2 0x08091c17 in game_loop_unix (control=8) at comm.c:1058
#3 0x080924d6 in main (argc=1701147238, argv=0xbfffd824) at comm.c:657
(gdb) list
1474
1475 // say WHA? (Zeroed! by Omega)
1476 wch = wch_next = ch = ch_next = vch = vch_next = victim = prev = NULL;
1477 for ( wch = char_list; wch != NULL; wch = wch_next )
1478 {
1479 wch_next = wch->next;
1480 if ( IS_NPC(wch)
1481 || wch->trust >= LEVEL_IMMORTAL
1482 || wch->in_room == NULL
1483 || wch->in_room->area->empty
(gdb) info locals
wch = 0x900044f
wch_next = 0x900044f
ch = 0x3
ch_next = 0x0
(gdb) frame 1
#1 0x0810b47e in update_handler () at update.c:1683
1683 aggr_update( );
(gdb) list
1678 {
1679 run_election();
1680 }
1681 */
1682
1683 aggr_update( );
1684 tail_chain( );
1685 return;
1686 }
1687
(gdb)
24 Sep, 2012, arholly wrote in the 17th comment:
Votes: 0
OK, another question. Why is this showing up in valgrind?
bool IS_NATURAL( CHAR_DATA *ch )
{
if(ch->race == race_lookup("werewolf") || ch->race == race_lookup("vampire"))
return FALSE;

return TRUE;
}


Is it because it's being used wrong? Here is a place it's used for example?
void update_pos( CHAR_DATA *victim, int agg )
{
if ( (victim->health + victim->agghealth - 7) > 0
&& (victim->position < P_SLEEP || victim->position > P_STAND) )
{
victim->position = P_STAND;
return;
}

if(IS_SET(victim->plr_flags, PLR_ARREST)
&& (victim->health + victim->agghealth - 7) <= 0)
{
victim->health = 6;
victim->agghealth = 7;
victim->position = P_STAND;
if(victim->fighting)
{
act("$N loads $n into a police cruiser to be taken to gaol.",
victim, NULL, victim->fighting, TO_NOTVICT, 0);
act("$N loads you into a police car and you are hauled away.",
victim, NULL, victim->fighting, TO_CHAR, 0);
act("You pack $n into a police car to be taken off to gaol.",
victim, NULL, victim->fighting, TO_VICT, 0);
}
else
{
act("The police load $n into a cruiser to be taken to gaol.",
victim, NULL, NULL, TO_NOTVICT, 0);
act("A group of police officers haul you away.",
victim, NULL, NULL, TO_CHAR, 1);
}
char_from_room(victim);
char_to_room(victim, get_room_index(ROOM_VNUM_GAOL));
return;
}

if (((IS_NATURAL(victim)) && ((victim->health + victim->agghealth - 7) < 0
|| (victim->health + victim->agghealth - 7) < 0))
|| ( (victim->health + victim->agghealth - 7) < 0 && victim->RBPG <= 1 ))
{
victim->position = P_DEAD;
return;
}

if ( (victim->health + victim->agghealth - 7) == 0 )
victim->position = P_INCAP;
if ( (victim->health + victim->agghealth - 7) < 0 )
{
if ( victim->race == race_lookup("human"))
victim->position = P_MORT;
else
if( victim->agghealth > 0 && !agg )
victim->position = P_TORPOR;
else
victim->position = P_MORT;
}

return;
}
24 Sep, 2012, Rarva.Riendf wrote in the 18th comment:
Votes: 0
Oliver said:
The memory management of RoM…? It just allocates memory, and instead of freeing the memory directly (to avoid problems like the one in this thread), it just clears/frees the object's variables and puts it in a "used" stack. If the "used" stack is not empty when the memory-allocation function is called, then it re-purposes the top object from the "used" stack as the new object. It's a memory recycling system. The objects that use this system have an IS_VALID flag to prevent accidental accessing of improperly-freed blocks.

It is not the theory of recycling process I had a problem with but with the fact it only worked if you only 'kill' one character at a time. And basically it did not avoid any problem, it just hid them (as if you acessed the variable it was still usuable sure, but it just meant strange behaviour as it should not have been accessed it in the first time). I always prefered a null pointer exception that is easy to spot and fix, than chasing a weird bug randomly occuring just cause I accessed a variable that should have been cleared.

And for <value optimized out>, yeah remove optimization, it wont make your mud really slower and provide a lot more usable gdb coredump.
24 Sep, 2012, arholly wrote in the 19th comment:
Votes: 0
Not sure that helps…

Quote
Program received signal SIGSEGV, Segmentation fault.
0x0813ad2d in aggr_update () at update.c:1479
1479 wch_next = wch->next;
(gdb) bt
#0 0x0813ad2d in aggr_update () at update.c:1479
#1 0x0813b1dd in update_handler () at update.c:1683
#2 0x08096d4c in game_loop_unix (control=8) at comm.c:1057
#3 0x080966ac in main (argc=2, argv=0xbfffd834) at comm.c:656
(gdb) list
1474
1475 // say WHA? (Zeroed! by Omega)
1476 wch = wch_next = ch = ch_next = vch = vch_next = victim = prev = NULL;
1477 for ( wch = char_list; wch != NULL; wch = wch_next )
1478 {
1479 wch_next = wch->next;
1480 if ( IS_NPC(wch)
1481 || wch->trust >= LEVEL_IMMORTAL
1482 || wch->in_room == NULL
1483 || wch->in_room->area->empty
(gdb) info locals
wch = 0x900044f
wch_next = 0x900044f
ch = 0x0
ch_next = 0x0
vch = 0x0
vch_next = 0x0
victim = 0x0
prev = 0x8388e88
(gdb) frame 1
#1 0x0813b1dd in update_handler () at update.c:1683
1683 aggr_update( );
(gdb) list
1678 {
1679 run_election();
1680 }
1681 */
1682
1683 aggr_update( );
1684 tail_chain( );
1685 return;
1686 }
1687
(gdb) info locals
pulse_area = 449
pulse_mobile = 1
pulse_violence = 17
pulse_time = 209
pulse_point = 209
pulse_msdp = 1
24 Sep, 2012, Rarva.Riendf wrote in the 20th comment:
Votes: 0
Something tells me it is not about the code but about a variable that had been overwritten or cleared before you get there.
Unless you fix all Valgrind errors, the reason every crash you have can come from 'anywhere' but where gdb say it crashed…
0.0/25