26 Jan, 2012, arholly wrote in the 1st comment:
Votes: 0
Hello:
So, I tried using Valgrind on my mud, because I was told it can help make things more efficient memory wise, and seeing how I'm based off of ROM2.4, I know that it isn't the most effective beast in the pack. Now, my mud normally starts up fine with no problems. It get's up running and carries on it's happy little way. However, when I tried doing Valgrind on it, this is what I got.
# valgrind -v –tool=memcheck –leak-check=full –show-reachable=yes –demangle=yes –db-attach=yes –num-callers=10 –track-origins=yes –track-fds=yes ../ptmud/src/project -v
==17678== Memcheck, a memory error detector
==17678== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==17678== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
==17678== Command: ../ptmud/src/project -v
==17678==
–17678– Valgrind options:
–17678– -v
–17678– –tool=memcheck
–17678– –leak-check=full
–17678– –show-reachable=yes
–17678– –demangle=yes
–17678– –db-attach=yes
–17678– –num-callers=10
–17678– –track-origins=yes
–17678– –track-fds=yes
–17678– Contents of /proc/version:
–17678– Linux version 2.6.18-274.7.1.el5.028stab095.1PAE (root@rhel5-build-x32) (gcc version 4.1.2 20080704 (Red Hat 4.1.2-46)) #1 SMP Mon Oct 24 21:55:06 MSD 2011
–17678– Arch and hwcaps: X86, x86-sse1-sse2
–17678– Page sizes: currently 4096, max supported 4096
–17678– Valgrind library directory: /usr/lib/valgrind
–17678– Reading syms from /lib/ld-2.5.so (0x97b000)
–17678– Reading syms from /home/m243bra/ptmud/src/project (0x8048000)
–17678– Reading syms from /usr/lib/valgrind/memcheck-x86-linux (0x38000000)
–17678– object doesn't have a dynamic symbol table
–17678– Reading suppressions file: /usr/lib/valgrind/default.supp
–17678– REDIR: 0x990910 (index) redirected to 0x3803e483 (vgPlain_x86_linux_REDIR_FOR_index)
–17678– Reading syms from /usr/lib/valgrind/vgpreload_core-x86-linux.so (0x4001000)
–17678– Reading syms from /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so (0x4003000)
==17678== WARNING: new redirection conflicts with existing – ignoring it
–17678– new: 0x00990910 (index ) R-> 0x040068c0 index
–17678– REDIR: 0x990ab0 (strlen) redirected to 0x4006aa0 (strlen)
–17678– Reading syms from /lib/libm-2.5.so (0xaf5000)
../ptmud/src/project: error while loading shared libraries: libc.so.6: failed to map segment from shared object: Cannot allocate memory
==17678== Jump to the invalid address stated on the next line
==17678== at 0x28A: ???
==17678== by 0x989285: _dl_signal_error (in /lib/ld-2.5.so)
==17678== by 0x98878E: _dl_map_object_deps (in /lib/ld-2.5.so)
==17678== by 0x97E432: dl_main (in /lib/ld-2.5.so)
==17678== by 0x98F13A: _dl_sysdep_start (in /lib/ld-2.5.so)
==17678== by 0x97C2B7: _dl_start (in /lib/ld-2.5.so)
==17678== by 0x97B816: ??? (in /lib/ld-2.5.so)
==17678== Address 0x28a is not stack'd, malloc'd or (recently) free'd
==17678==
==17678==
==17678== —- Attach to debugger ? — [Return/N/n/Y/y/C/c] —- Y
==17678== starting debugger with cmd: /usr/bin/gdb -nw /proc/17839/fd/2038 17839
GNU gdb (GDB) Red Hat Enterprise Linux (7.0.1-37.el5_7.1)
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>;
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i386-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...;
Reading symbols from /proc/17839/fd/2038…done.
Attaching to program: /proc/17839/fd/2038, process 17839
Reading symbols from /lib/ld-linux.so.2…(no debugging symbols found)…done.
Loaded symbols for /lib/ld-linux.so.2
Reading symbols from /usr/lib/valgrind/vgpreload_core-x86-linux.so…done.
Loaded symbols for /usr/lib/valgrind/vgpreload_core-x86-linux.so
Reading symbols from /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so…done.
Loaded symbols for /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so
Reading symbols from /lib/libm.so.6…(no debugging symbols found)…done.
Loaded symbols for /lib/libm.so.6
0x0000028a in ?? ()
(gdb) bt
#0 0x0000028a in ?? ()
#1 0x040013b3 in _vgnU_freeres () at vg_preloaded.c:62
#2 0x00989286 in _dl_signal_error () from /lib/ld-linux.so.2
#3 0x0098878f in _dl_map_object_deps () from /lib/ld-linux.so.2
#4 0x0097e433 in dl_main () from /lib/ld-linux.so.2
#5 0x0098f13b in _dl_sysdep_start () from /lib/ld-linux.so.2
#6 0x0097c2b8 in _dl_start () from /lib/ld-linux.so.2
#7 0x0097b817 in _start () from /lib/ld-linux.so.2
(gdb) frame 0
#0 0x0000028a in ?? ()
(gdb) info locals
No symbol table info available.
(gdb) list
347 int main( int argc, char **argv )
348 {
349 struct timeval now_time;
350
351 bool fCopyOver = FALSE;
352
353 /*
354 * Init time.
355 */
356 gettimeofday( &now_time, NULL );
(gdb)

Clearly, it's crashing on startup when I run Valgrind, that much I can figure out. The rest though I have no idea about. Can anyone help me out?

Thanks in advance,
Arholly
26 Jan, 2012, Davion wrote in the 2nd comment:
Votes: 0
try typing 'continue' when it does that. I know it has a problem with copyover.
26 Jan, 2012, Omega wrote in the 3rd comment:
Votes: 0
Quote
error while loading shared libraries: libc.so.6: failed to map segment from shared object: Cannot allocate memory


I think he is out of memory on his VPS… Perhaps valgrind exceeds his max memory.
26 Jan, 2012, arholly wrote in the 4th comment:
Votes: 0
I get this:
Program received signal SIGSEGV, Segmentation fault.
0x0000028a in ?? ()


Davion said:
try typing 'continue' when it does that. I know it has a problem with copyover.
26 Jan, 2012, arholly wrote in the 5th comment:
Votes: 0
Ok, so then I went and looked at the core and got this:
Program terminated with signal 11, Segmentation fault.
#0 0x38062011 in do_clone (ch=0x0, argument=0x0) at act_wiz.c:2307
2307 clone_object(obj,clone);
(gdb) bt
#0 0x38062011 in do_clone (ch=0x0, argument=0x0) at act_wiz.c:2307
#1 0x38052454 in find_keeper (ch=0x0, argument=0xbeec259e "\354\276\f&\354\276\314%\354\276K\311\003\070\f&\354\276\020%") at act_obj.c:2626
#2 0x380526c5 in do_shoplift (ch=0x3802780d, argument=<value optimized out>) at act_obj.c:3425
#3 0x380526f1 in do_shoplift (ch=0x1, argument=0x0) at act_obj.c:3434
#4 0x3803c20b in do_count (ch=0x3802780d, argument=0x0) at act_info.c:2560
#5 0x3803c2bb in do_who (ch=0xbeec266c, argument=0xbeec266c "\rx\002\070") at act_info.c:2346
#6 0x38027874 in ?? ()
#7 0xbeec266c in ?? ()
#8 0x00000001 in ?? ()
#9 0x00000064 in ?? ()
#10 0x00000000 in ?? ()
(gdb) frame 0
#0 0x38062011 in do_clone (ch=0x0, argument=0x0) at act_wiz.c:2307
2307 clone_object(obj,clone);
(gdb) info locals
clone = 0x0
arg = '\000' <repeats 840 times>, "\002\000\000\000\000\000\001\001\030\340\355gi\001\000\000H\200\rh\rx\002\070T%\354\276 %\354\276K#\005\070H\200\rh\rx\002\070\001\000\000\000\001\000\000\000\265\261\t\001P%\354\276"
rest = <value optimized out>
mob = <value optimized out>
obj = 0x67e3197e
(gdb)


Edit: which is this function:
void do_clone(CHAR_DATA *ch, char *argument )
{
char arg[MAX_INPUT_LENGTH];
char *rest;
CHAR_DATA *mob;
OBJ_DATA *obj;

rest = one_argument(argument,arg);

if (arg[0] == '\0')
{
send_to_char("Clone what?\n\r",ch);
return;
}

if (!str_prefix(arg,"object"))
{
mob = NULL;
obj = get_obj_here(ch,rest);
if (obj == NULL)
{
send_to_char("You don't see that here.\n\r",ch);
return;
}
}
else if (!str_prefix(arg,"mobile") || !str_prefix(arg,"character"))
{
obj = NULL;
mob = get_char_room(ch,rest);
if (mob == NULL)
{
send_to_char("You don't see that here.\n\r",ch);
return;
}
}
else /* find both */
{
mob = get_char_room(ch,argument);
obj = get_obj_here(ch,argument);
if (mob == NULL && obj == NULL)
{
send_to_char("You don't see that here.\n\r",ch);
return;
}
}

/* clone an object */
if (obj != NULL)
{
OBJ_DATA *clone;

if (!obj_check(ch,obj))
{
send_to_char(
"Your powers are not great enough for such a task.\n\r",ch);
return;
}

clone = create_object(obj->pIndexData);
clone_object(obj,clone);
if (obj->carried_by != NULL)
obj_to_char(clone,ch);
else
obj_to_room(clone,ch->in_room);
recursive_clone(ch,obj,clone);

act("$n has created $p.",ch,clone,NULL,TO_ROOM,0);
act("You clone $p.",ch,clone,NULL,TO_CHAR,0);
wiznet("$N clones $p.",ch,clone,WIZ_LOAD,WIZ_SECURE,get_trust(ch));
return;
}
else if (mob != NULL)
{
CHAR_DATA *clone;
OBJ_DATA *new_obj;
char buf[MAX_STRING_LENGTH];

if (!IS_NPC(mob))
{
send_to_char("You can only clone mobiles.\n\r",ch);
return;
}

if (!IS_TRUSTED(ch,LEVEL_IMMORTAL))
{
send_to_char(
"Your powers are not great enough for such a task.\n\r",ch);
return;
}

clone = create_mobile(mob->pIndexData);
clone_mobile(mob,clone);

for (obj = mob->carrying; obj != NULL; obj = obj->next_content)
{
if (obj_check(ch,obj))
{
new_obj = create_object(obj->pIndexData);
clone_object(obj,new_obj);
recursive_clone(ch,obj,new_obj);
obj_to_char(new_obj,clone);
new_obj->wear_loc = obj->wear_loc;
}
}
char_to_room(clone,ch->in_room);
act("$n has created $N.",ch,NULL,clone,TO_ROOM,0);
act("You clone $N.",ch,NULL,clone,TO_CHAR,0);
sprintf(buf,"$N clones %s.",clone->short_descr);
wiznet(buf,ch,NULL,WIZ_LOAD,WIZ_SECURE,get_trust(ch));
return;
}
}
26 Jan, 2012, kiasyn wrote in the 6th comment:
Votes: 0
your problem is not in do_clone, its before do_clone
#0  0x38062011 in do_clone (ch=0x0, argument=0x0) at act_wiz.c:2307
#1 0x38052454 in find_keeper (ch=0x0, argument=0xbeec259e "\354\276\f&\354\276\314%\354\276K\311\003\070\f&\354\276\020%") at act_obj.c:2626
#2 0x380526c5 in do_shoplift (ch=0x3802780d, argument=<value optimized out>) at act_obj.c:3425
#3 0x380526f1 in do_shoplift (ch=0x1, argument=0x0) at act_obj.c:3434
#4 0x3803c20b in do_count (ch=0x3802780d, argument=0x0) at act_info.c:2560
#5 0x3803c2bb in do_who (ch=0xbeec266c, argument=0xbeec266c "\rx\002\070") at act_info.c:2346

see the ch pointer, 0x1 is a bad pointer, 0x0 is null… so the wrong variable is getting passed from count to shoplift to keeper to clone…. which really seems like something funky is happening in that stack trace because i wouldn't think those commands would stack in that order.
26 Jan, 2012, Omega wrote in the 7th comment:
Votes: 0
His stack is trash Kiasyn. do_count doesn't call do_shoplift at all in his code.

Its a command, and its not being executed, either he recompiled his mud after the crash and gdb'd a bad-core in comparison. Or his stack is completely out to lunch.. I think its trashed due to a complete and utter memory corruption in the core of his mud.

With that being said, his do_who command doesn't call do_count either. Which leads me to further believe that this is just completely wrong. Hands down, wrong.

I think he needs to rip out that stock rom memory management system, (stupid recyclers) and rewrite the code properly. calloc/free, (since he isn't using c++) and write better, safer coder.
27 Jan, 2012, Rarva.Riendf wrote in the 8th comment:
Votes: 0
Yeah unfortunately Valgrind pukes on ROM 'memory management'. It is a quite an annoying job to rewrite anything but it has to be done. I discussed this problem some years ago :) And the easier and proved working solution is delayed extraction for object and character. (delayed extraction is CircleMud right ?)
It uncovered a bunch of bugs that were hidden by the memory management as well (using variable that should be cleared but the pointer being still valid, no crash, just weird behaviour from time to time)

Good luck, it took me a lot of time to iron it all. But I am soooo happy I did it.

And Valgrind complaining means there are bugs. The fact it runs 'fine' when not using it is just sheer luck.
29 Jan, 2012, arholly wrote in the 9th comment:
Votes: 0
Alright, so let me see if anyone can see any problems in some of those functions. I'd appreciate any help or insight. Thanks in advance for any help or insight…
void do_who( CHAR_DATA *ch, char *argument )
{
char buf[MAX_STRING_LENGTH];
char buf2[MAX_STRING_LENGTH];
BUFFER *output;
DESCRIPTOR_DATA *d;
int iRace;
int iClan;
int iLevelLower;
int iLevelUpper;
int nNumber;
int nMatch;
int app;
bool rgfClan[MAX_CLAN];
bool rgfRace[MAX_PC_RACE];
bool fClanRestrict = FALSE;
bool fClan = FALSE;
bool fRaceRestrict = FALSE;
bool fImmortalOnly = FALSE;
bool fRPOK = FALSE;
bool fPack = FALSE;
PACK_DATA *pack = NULL;

/*
* Set default arguments.
*/
iLevelLower = 0;
iLevelUpper = MAX_LEVEL;
for ( iRace = 0; iRace < MAX_PC_RACE; iRace++ )
rgfRace[iRace] = FALSE;
for (iClan = 0; iClan < MAX_CLAN; iClan++)
rgfClan[iClan] = FALSE;

send_to_char("\n\r", ch);

send_to_char( "\t[F220]************************************************************\tn\n\r", ch);
send_to_char( "\t[F220]***\tn \tWThese are the people currently on Project Twilight\tn \t[F220]***\tn\n\r", ch );
send_to_char( "\t[F220]************************************************************\tn\n\r", ch);

/*
* Parse arguments.
*/
nNumber = 0;
for ( ;; )
{
char arg[MAX_STRING_LENGTH];

argument = one_argument( argument, arg );
if ( arg[0] == '\0' )
break;

/*
* Look for clan to turn on.
*/
if (!str_prefix(arg,"admin") || !str_prefix(arg,"staff"))
{
fImmortalOnly = TRUE;
send_to_char( "\t[F220]***\tn \tW PT Staff \tn \t[F220]***\tn\n\r", ch );
send_to_char( "\t[F220]************************************************************\tn\n\r", ch);

}
else if (!str_prefix(arg, "available") || !str_prefix(arg, "rpok") || !str_prefix(arg, "rpmod"))
{
fRPOK = TRUE;
send_to_char( "\t[F220]***\tn \tW RP Available \tn \t[F220]***\tn\n\r", ch );
send_to_char( "\t[F220]************************************************************\tn\n\r", ch);

}
else if (!str_prefix(arg, "pack"))
{
fPack = TRUE;
if(!IS_ADMIN(ch) || argument[0] == '\0')
pack = pack_lookup(ch->pack);
else
pack = pack_lookup(argument);

if(pack == NULL)
{
if(!IS_ADMIN(ch) || argument[0] == '\0')
send_to_char("You aren't part of a pack.\n\r", ch);
else
send_to_char("No such pack.\n\r", ch);
}
}
else if(IS_ADMIN(ch))
{
iRace = race_lookup(arg);

if (iRace == 0 || iRace >= MAX_PC_RACE)
{
if (!str_prefix(arg,"clan"))
fClan = TRUE;
else
{
iClan = clan_lookup(arg);
if (iClan)
{
fClanRestrict = TRUE;
rgfClan[iClan] = TRUE;
}
else
{
send_to_char("That's not a valid race, kith, tribe or clan.\n\r", ch);
return;
}
}
}
else
{
fRaceRestrict = TRUE;
rgfRace[iRace] = TRUE;
}
}
}

/*
* Add a header.
*/
if(fPack && pack != NULL)
{
sprintf(buf, "The %s Pack\n\r", pack->name);
send_to_char(buf, ch);
}

/*
* Now show matching chars.
*/
nMatch = 0;
buf[0] = '\0';
output = new_buf();
for ( d = descriptor_list; d != NULL; d = d->next )
{
CHAR_DATA *wch;
char const *clan;

/*
* Check for match against restrictions.
*/
if ( d->connected != CON_PLAYING || !can_see_main( ch, d->character ) )
continue;

wch = ( d->original != NULL ) ? d->original : d->character;

if (!can_see_main(ch,wch))
continue;

if ( ( fImmortalOnly && !IS_ADMIN(wch) )
|| ( fRaceRestrict && !rgfRace[wch->race])
|| ( fClan && !is_clan(wch))
|| ( fClanRestrict && !rgfClan[wch->clan])
|| ( fRPOK && !IS_SET(wch->plr_flags, PLR_RP_OK)))
continue;

if ( fPack && pack != pack_lookup(wch->pack) )
continue;

nMatch++;

/*
* Figure out stuff to print.
*/
clan = clan_table[wch->clan].who_name;
app = get_curr_stat(wch, STAT_APP);
send_to_char("\n\r", ch);

/*
* Format it up.
*/
if(IS_SET(ch->comm, COMM_BRIEF))
{
if(IS_ADMIN(ch))
{
sprintf( buf, "[\tY%4s %s\tn][\tY%6s] %s%s%s\tW%s\tn\n\r",
wch->race < MAX_PC_RACE ? pc_race_table[wch->race].who_name
: " ",
clan,
gender_string(wch),
wch->invis_level >= LEVEL_IMMORTAL ? "[\tYWIZI\tn]" : "",
IS_SET(wch->act2, ACT2_STORY) ? "[\t[F205]ST\tn]": "",
IS_SET(wch->comm, COMM_AFK) ? "[\tYAFK\tn]": "",
wch->name);
}
else
{
sprintf( buf, "[%s] %s%s\tW%s\tn\n\r",
gender_string(wch),
IS_SET(wch->act2, ACT2_STORY) ? "[\t[F205]ST\tn]": "",
IS_SET(wch->comm, COMM_AFK) ? "[\tYAFK\tn]": "",
wch->name );
}
}
else
{
if(IS_ADMIN(ch))
sprintf( buf,
"[\tY%4s %s\tn][\tY%s %6s\tn]%s%s%s \tW%s%s%s\tn %s%s%s\tn\n\r",
wch->race < MAX_PC_RACE ? pc_race_table[wch->race].who_name
: " ",
clan,
appearance_string(wch),
gender_string(wch),
wch->invis_level >= LEVEL_IMMORTAL ? "[\tYWIZI\tn]" : "",
IS_SET(wch->act2, ACT2_STORY) ? "[\t[F205]ST\tn]": "",
IS_SET(wch->comm, COMM_AFK) ? "[\tYAFK\tn]": "",
wch->name,
wch->surname[0] != '\0' ? " ":"",
wch->surname,
fRPOK ? " [": "",
IS_NPC(wch) ? "" : !fRPOK ? wch->pcdata->title : wch->pcdata->rpok_string,
fRPOK ? "]": "");
else
sprintf( buf, "[%s]%s%s \tW%s%s%s\tn\tR%s\tn%s\tR%s\tn\n\r",
gender_string(wch),
IS_SET(wch->act2, ACT2_STORY) ? "[\t[F205]ST\tn]": "",
IS_SET(wch->comm, COMM_AFK) ? "[\tYAFK\tn]": "",
wch->name,
wch->surname[0] != '\0' ? " ":"",
wch->surname,
fRPOK ? " [": "",
IS_NPC(wch) ? "" : !fRPOK ? wch->pcdata->title : wch->pcdata->rpok_string,
fRPOK ? "]": "");
}
add_buf(output,buf);
}

sprintf( buf2, "\n\rPlayers found: %d\n\r", nMatch );
add_buf(output,buf2);
page_to_char( buf_string(output), ch );
free_buf(output);
return;
}

void do_count ( CHAR_DATA *ch, char *argument )
{
int count;
DESCRIPTOR_DATA *d;
char buf[MAX_STRING_LENGTH];

count = 0;

for ( d = descriptor_list; d != NULL; d = d->next )
if ( d->connected == CON_PLAYING && can_see_main( ch, d->character ) )
count++;

max_on = UMAX(count,max_on);

if (max_on == count)
sprintf(buf,"There are %d characters on, the most so far today.\n\r",count);
else
sprintf(buf,"There are %d characters on, the most on today was %d.\n\r",count,max_on);

send_to_char(buf,ch);
}

void do_shoplift( CHAR_DATA *ch, char *argument )
{
CHAR_DATA *victim;
OBJ_DATA *obj;
OBJ_DATA *t_obj;
EXTRA_DESCR_DATA *ed, *objed;
int percent, fail;
char buf [MAX_STRING_LENGTH];
char arg1 [MAX_INPUT_LENGTH];
char arg2 [MAX_INPUT_LENGTH];

argument = one_argument( argument, arg1 );
argument = one_argument( argument, arg2 );

if(IS_SET(ch->plr_flags, PLR_RP_OK))
{
send_to_char("For your own safety, you can't shoplift in RP mode.\n\r", ch);
return;
}

if ( arg1[0] == '\0' || arg2[0] == '\0' )
{
send_to_char( "Steal what from whom?\n\r", ch );
return;
}

if ( ( victim = find_keeper( ch, arg2 ) ) == NULL )
{
send_to_char( "There's no shop here.\n\r", ch );
return;
}

if ( victim == ch )
{
send_to_char( "That's pointless.\n\r", ch );
return;
}

WAIT_STATE( ch, skill_table[gsn_steal].beats );
percent = get_curr_stat(victim, STAT_DEX) + victim->ability[ALERTNESS].value;

if (!IS_AWAKE(victim))
percent -= 1;
else if (!can_see(victim,ch))
percent += 2;
else
percent += 3;

if (percent > 10) percent = 10;
if (percent < 6) percent = 6;

fail = dice_rolls(ch, get_curr_stat(ch, STAT_DEX) + ch->ability[SUBTERFUGE].value, percent);

if ( ( !IS_NPC(ch) && (fail <= 0) )
|| ( !IS_NPC(ch) && !is_clan(ch)) )
{
/*
* Failure.
*/
send_to_char( "Oops.\n\r", ch );
affect_strip(ch,gsn_sneak);
REMOVE_BIT(ch->affected_by,AFF_SNEAK);

act( "$n tried to steal from you.\n\r", ch, NULL, victim, TO_VICT, 0 );
act( "$n tried to steal from $N.\n\r", ch, NULL, victim, TO_NOTVICT,0);
snprintf( buf, MSL, "%s is a thief!", ch->name );

if (!IS_AWAKE(victim))
do_function(victim, &do_wake, "");
if (IS_AWAKE(victim) && IS_NPC(victim))
{
do_function(victim, &do_yell, buf);
}
if ( !IS_NPC(ch) )
{
if ( IS_NPC(victim) )
{
multi_hit( victim, ch, TYPE_UNDEFINED );
}
else
{
snprintf(buf, MSL, "$N tried to steal from %s.",victim->name);
wiznet(buf,ch,NULL,WIZ_FLAGS,0,0);
}
}
if(!IS_SET(victim->act2, ACT2_NOWARRANT))
add_warrant(ch, 3, TRUE);

return;
}

if(!IS_SET(victim->act2, ACT2_NOWARRANT))
add_warrant(ch, 3, FALSE);

if ( ( obj = get_obj_carry( victim, arg1, ch ) ) == NULL )
{
send_to_char( "You can't find it.\n\r", ch );
return;
}

if ( !can_drop_obj( ch, obj ) )
{
send_to_char( "You can't pry it away.\n\r", ch );
return;
}

if ( ch->carry_number + get_obj_number( obj ) > can_carry_n( ch ) )
{
send_to_char( "You have your hands full.\n\r", ch );
return;
}

if ( ch->carry_weight + get_obj_weight( obj ) > can_carry_w( ch ) )
{
send_to_char( "You can't carry that much weight.\n\r", ch );
return;
}

if ( IS_SET( obj->extra_flags, ITEM_INVENTORY ) && IS_NPC(victim) )
{
t_obj = create_object( obj->pIndexData );
if(IS_SET(t_obj->extra_flags, ITEM_INVENTORY))
REMOVE_BIT(t_obj->extra_flags, ITEM_INVENTORY);
if(IS_SET(victim->act2, ACT2_NEWS_STAND))
{
free_string(t_obj->name);
t_obj->name = str_dup(obj->name);
free_string(t_obj->short_descr);
t_obj->short_descr = str_dup(obj->short_descr);
free_string(t_obj->description);
t_obj->description = str_dup(obj->description);

t_obj->cost = obj->cost;

for(objed=obj->extra_descr;objed;objed=objed->next)
{
/* Set extra descriptions for articles */
ed = alloc_perm( sizeof(*ed) );
ed->keyword = str_dup(objed->keyword);
ed->description = str_dup(objed->description);
ed->next = t_obj->extra_descr;
t_obj->extra_descr = ed;
}

t_obj->wear_loc = -1;
free_string(t_obj->full_desc);
t_obj->full_desc = str_dup(obj->full_desc);
}
}
else
{
t_obj = obj;
obj = obj->next_content;
obj_from_char( t_obj );
if(IS_SET(t_obj->extra_flags, ITEM_INVENTORY))
REMOVE_BIT(t_obj->extra_flags, ITEM_INVENTORY);
}

if (t_obj->timer > 0 && !IS_OBJ_STAT(t_obj,ITEM_HAD_TIMER))
t_obj->timer = 0;
REMOVE_BIT(t_obj->extra_flags,ITEM_HAD_TIMER);
obj_to_char( t_obj, ch );

act("You pocket $p.",ch,obj,NULL,TO_CHAR,0);
send_to_char( "Got it!\n\r", ch );
return;
}

CHAR_DATA *find_keeper( CHAR_DATA *ch, char *argument )
{
/*char buf[MAX_STRING_LENGTH];*/
CHAR_DATA *keeper;
SHOP_DATA *pShop;

pShop = NULL;

if(argument[0] == '\0')
{
send_to_char( "You must supply a valid shopkeeper.\n\r", ch );
return NULL;
}

for ( keeper = ch->in_room->people; keeper; keeper = keeper->next_in_room )
{
if ( ( IS_NPC(keeper) && (pShop = keeper->pIndexData->pShop) != NULL )
|| ( !IS_NPC(keeper) && !str_cmp(keeper->profession, "Salesman") )
|| ( !IS_NPC(keeper) && (!str_cmp(keeper->profession, "Chef")
|| !str_cmp(keeper->profession, "Maker")) && !str_cmp(ch->profession, "Salesman") ) )
if(ch != keeper && keeper == get_char_room(ch, argument))
break;
}

if(keeper == NULL)
{
send_to_char( "You can't do that here.\n\r", ch );
return NULL;
}

if ( pShop == NULL && !(!str_cmp(keeper->profession,"Chef") || !str_cmp(keeper->profession,"Salesman")
|| !str_cmp(keeper->profession,"Maker")) )
{
send_to_char( "You can't do that here.\n\r", ch );
return NULL;
}

if(str_cmp(ch->profession,"Salesman") && (!str_cmp(keeper->profession, "Chef") || !str_cmp(keeper->profession, "Maker")))
{
send_to_char( "You can't do that here.\n\r", ch );
return NULL;
}

/*
* Shop hours.
*/
if(pShop)
{
if ( time_info.hour < pShop->open_hour )
{
do_function(keeper, &do_say, "Sorry, I am closed. Come back later.");
return NULL;
}

if ( time_info.hour > pShop->close_hour )
{
do_function(keeper, &do_say, "Sorry, I am closed. Come back tomorrow.");
return NULL;
}
}

/*
* Invisible or hidden people.
*/
if ( !can_see( keeper, ch ) )
{
do_function(keeper, &do_say, "I don't trade with folks I can't see.");
return NULL;
}

return keeper;
}

void do_clone(CHAR_DATA *ch, char *argument )
{
char arg[MAX_INPUT_LENGTH];
char *rest;
CHAR_DATA *mob;
OBJ_DATA *obj;

rest = one_argument(argument,arg);

if (arg[0] == '\0')
{
send_to_char("Clone what?\n\r",ch);
return;
}

if (!str_prefix(arg,"object"))
{
mob = NULL;
obj = get_obj_here(ch,rest);
if (obj == NULL)
{
send_to_char("You don't see that here.\n\r",ch);
return;
}
}
else if (!str_prefix(arg,"mobile") || !str_prefix(arg,"character"))
{
obj = NULL;
mob = get_char_room(ch,rest);
if (mob == NULL)
{
send_to_char("You don't see that here.\n\r",ch);
return;
}
}
else /* find both */
{
mob = get_char_room(ch,argument);
obj = get_obj_here(ch,argument);
if (mob == NULL && obj == NULL)
{
send_to_char("You don't see that here.\n\r",ch);
return;
}
}

/* clone an object */
if (obj != NULL)
{
OBJ_DATA *clone;

if (!obj_check(ch,obj))
{
send_to_char( "Your powers are not great enough for such a task.\n\r",ch);
return;
}

clone = create_object(obj->pIndexData);
clone_object(obj,clone);
if (obj->carried_by != NULL)
obj_to_char(clone,ch);
else
obj_to_room(clone,ch->in_room);
recursive_clone(ch,obj,clone);

act("$n has created $p.",ch,clone,NULL,TO_ROOM,0);
act("You clone $p.",ch,clone,NULL,TO_CHAR,0);
wiznet("$N clones $p.",ch,clone,WIZ_LOAD,WIZ_SECURE,get_trust(ch));
return;
}
else if (mob != NULL)
{
CHAR_DATA *clone;
OBJ_DATA *new_obj;
char buf[MAX_STRING_LENGTH];

if (!IS_NPC(mob))
{
send_to_char("You can only clone mobiles.\n\r",ch);
return;
}

if (!IS_TRUSTED(ch,LEVEL_IMMORTAL))
{
send_to_char( "Your powers are not great enough for such a task.\n\r",ch);
return;
}

clone = create_mobile(mob->pIndexData);
clone_mobile(mob,clone);

for (obj = mob->carrying; obj != NULL; obj = obj->next_content)
{
if (obj_check(ch,obj))
{
new_obj = create_object(obj->pIndexData);
clone_object(obj,new_obj);
recursive_clone(ch,obj,new_obj);
obj_to_char(new_obj,clone);
new_obj->wear_loc = obj->wear_loc;
}
}
char_to_room(clone,ch->in_room);
act("$n has created $N.",ch,NULL,clone,TO_ROOM,0);
act("You clone $N.",ch,NULL,clone,TO_CHAR,0);
snprintf(buf, MSL, "$N clones %s.",clone->short_descr);
wiznet(buf,ch,NULL,WIZ_LOAD,WIZ_SECURE,get_trust(ch));
return;
}
}
29 Jan, 2012, Davion wrote in the 10th comment:
Votes: 0
You are asking the impossible. There are various reference points that we just don't have. Not to mention the going theory is your stack dump is garbage so your problem likely isn't in any of those places.
30 Jan, 2012, Omega wrote in the 11th comment:
Votes: 0
I've seen his mud, his problem is it is a massive memory leak. There are so very many problems laying around in his code, you fix one issue, and another one pops up. Its like plugging holes in a sinking ship. Until he finds the real problem, all you'll be doing is putting bandaids on it.
30 Jan, 2012, Tijer wrote in the 12th comment:
Votes: 0
had a similar issue on my mud… crashes all over the place… believe we have finally found the root cause of the problem… fingers crossed…….
30 Jan, 2012, Rarva.Riendf wrote in the 13th comment:
Votes: 0
When you have leaks it can crash anywhere, really anywhere. In a method you could write memory in a place where another value is stored, and two days after when this value is finally used and processed, be lucky and only have scrambled output cause you used it as a char array, or a crash if you used it as a pointer.
Valgrind can help detect those leaks, provided you actually manage memory in a sane way in the first place. If Valgrind cannot run a single mud…be very afraid, as way bigger/complex projects run perfectly fine through it, with very seldom warnings

If your mud is in C, run everything new you write through it before you put it in production.
It will not avoid a crash, but it will make so your crash because you forgot to test something but at least create a meaningful core dump provided you at least tested common cases.
30 Jan, 2012, David Haley wrote in the 14th comment:
Votes: 0
Rarva, you're mixing up memory leaks and something else.
A memory leak is when you lose a pointer to allocated memory. It has nothing to do with overwriting useful values.

Yes, having memory leaks can cause crashes, but because you ran out of memory and attempted to allocate (and didn't check the allocation result for 'null'), not because you got unexpected values… that's another problem.
30 Jan, 2012, Rarva.Riendf wrote in the 15th comment:
Votes: 0
David Haley said:
Rarva, you're mixing up memory leaks and something else.
A memory leak is when you lose a pointer to allocated memory. It has nothing to do with overwriting useful values.

Already have this conversation, most people also consider a leak as filling a bucket with more water than it can contains that then leak everywhere on the ground.
Like writing memory some bytes more than your allocated space. Feel free to correct me everytime I use the term memory leak this way, I don't care.
30 Jan, 2012, David Haley wrote in the 16th comment:
Votes: 0
That's a buffer overflow: writing beyond your allocated memory space. That is not a memory leak.

I'm not sure why you're so hostile and insist on using terminology incorrectly, it's just confusing and will give people incorrect information.

But don't take my word for the definition if you don't want to… http://en.wikipedia.org/wiki/Memory_leak

"A memory leak, in computer science (or leakage, in this context), occurs when a computer program consumes memory but is unable to release it back to the operating system. In object-oriented programming, a memory leak happens when an object is stored in memory but cannot be accessed by the running code."
30 Jan, 2012, Rarva.Riendf wrote in the 17th comment:
Votes: 0
Quote
I'm not sure why you're so hostile and insist on using terminology incorrectly, it's just confusing and will give people incorrect information.

Considering I described how it happens I doubt it, and I call eveything memory related a memory leak anyway. (cause I use it as a water leaking analogy, not pure IT jargon).
The hostility you feel probably comes from me not being a native english speaker. Was just reminding we already have this conversation, and even if you are 'technically' right, no need to argue about it again with me, I do not care.
30 Jan, 2012, David Haley wrote in the 18th comment:
Votes: 0
It's really unfortunate that you're using incorrect terminology, and you know it's incorrect, and you don't care. :sad:
30 Jan, 2012, Rarva.Riendf wrote in the 19th comment:
Votes: 0
I doubt it changes anything to the point I was making. Memory leaks are usually easy to fix once you detect them. Buffers overflow on the other hand….And Darien was using the term memory leak, if it was only memory leak all over the place it would be easy to detect that Valgrind pukes about that (just need to check to have top launched in a term to check).
30 Jan, 2012, arholly wrote in the 20th comment:
Votes: 0
Alright, as the OP and a newbie coder, what does it mean when you keep saying "my stack is trashed" and the like? I understand (conceptually) what a leak is but it doesn't help me much in trying to track it down.
0.0/26