[LONG] Offending strcpy, segementation fault, saving object short description

From: Jason Stortz (JI-Stortz@WIU.EDU)
Date: 07/22/00

Dear Peers,
 My goal here is to ask for help in making short descriptions of
objects save.  When I started this project the values v0 through v3, four
in all, saved automatically.  I increased the number of values from four(4)
to ten(10).  That went fine.  Now, onward: the short description.
 First, let's get familiar with some things you will be seeing
shortly.  Primarly a command and a function.  The command is "restring",
which I created to enable me to redo the short description of an item in my
inventory so the gods can create custom items for quests, etc.  Using
restring we can change the short description of an object, and now our goal
is to save that.  The restring function works fine, and is not part of the
problem.  The function we need to be familar with is "logtest(char *line)"
which simply takes a string "line" and writes it out to a file to help us
track our way through the saving process.  That said, lets move on.
 Oh yes.  The obvious thing to say before starting is EXACTLY whats
wrong, yes?  Well, we try to save the short_description of the object and
it works during one routine: quit.  When we have an object in inventory and
type quit everthing is fine.  Log back in and the object is still in
inventory with CORRECT short description.  This means that if we didn't
change the descrip the object is as was when we quit and if we *DID* use
the restring command to change the descrip then when we logged back in the
object had the *NEW* short descrip that we changed to before typing quit.
Stick with me. =)  Now, the real problem occurs when one of two things
happen.  A shutdown die command, or a save command will issue forth this:

./autorun line 92: 2202 Segmentation fault bin/circle $FLAGS $PORT >>syslog
 So, let's get down to the nitty gritty, the code.  I *THINK* I have
narrowed down the code problems to the offending line, but have no clue why
it is having problems.  In case A I show you the problematic code.  In case
B I have commented out the line that I think is a problem and made some
comments on it.
 From structs.h --> Notice the int value[10] which used to be int
value[4].  Part of the changes I referred to earlier that works
wonderfully.  Then notice the char *short_description; part in
/* object flags; used in obj_data */
struct obj_flag_data {
   int value[10]; /* Values  *--> Notice I changed this <--* */
   byte type_flag; /* Type of item       */
   int /*bitvector_t*/ wear_flags; /* Where you can wear it*/
   int /*bitvector_t*/ extra_flags; /* If it hums, glows, etc.*/
   int weight;  /* Weigt what else                  */
     /* etc, etc... */
/* ================== Memory Structure for Objects ================== */
struct obj_data {
   obj_vnum item_number; /* Where in data-base   */
   room_rnum in_room;  /* In what room -1 when conta/carr */

   struct obj_flag_data obj_flags;/* Object information               */
   struct obj_affected_type affected[MAX_OBJ_AFFECT];  /* affects */

   char *name;                    /* Title of object :get etc.        */
   char *description;    /* When in room                     */
   char *short_description;       /* when worn/carry/in cont.         */
   char *action_description;      /* What to write when used          */
   struct extra_descr_data *ex_description; /* extra descriptions     */
 /* etc, etc... */
struct obj_file_elem {
   obj_vnum item_number;
   sh_int location;
   int value[10];
   char *short_description;  /*  *--> Notice, I added this. <--*  */
   int /*bitvector_t*/ extra_flags;
   int weight;
 /* etc, etc... */
 Now here is were we really get down to it.  This is the function
with what I *think* is the offending line of code.  This code comes form
int Obj_to_store(struct obj_data * obj, FILE * fl, int location)
  int j;
  struct obj_file_elem object;
  char test[MAX_STRING_LENGTH];
  logtest("    Starting Obj_to_store.\r\n");
             // Notice the logtest writing stuff
             // out for us.  You'll see it again
  object.item_number = GET_OBJ_VNUM(obj);
  object.location = location;
 /* More logtest, I'll show you teh output in a minute. */
 logtest("Starting Object values in objsave.c Obj_to_store.\r\n");
  object.value[0] = GET_OBJ_VAL(obj, 0);
  object.value[1] = GET_OBJ_VAL(obj, 1);
  object.value[2] = GET_OBJ_VAL(obj, 2);
    /* On through ... */
  object.value[9] = GET_OBJ_VAL(obj, 9);
 /* If we see this in the logtest output file it proves all is okay*/
 logtest(" ********** Finished object storing in objsave.c.\r\n");

/* This is to make sure that the GET_OBJ_SHORT macro working correctly. */
  sprintf(test," Obj_ to_store: GET_OBJ_short(obj):%s.\r\n",
/* ---> HERE IT IS!! <--- This is the offending line of code.  In this,
case A I have not commented out this line of code.  Look directly after the
strcpy call and you'll see the next logtest call.  In case A(without the
strcpy commented out) we never get to the logtest call after strcpy. */
 /* Here we are.  In Case A we never make it this far. */
 logtest("Copy is over.\r\n");
 /* Again, testing to see in the short description has changed. */
  sprintf(test," Obj_ to_store: GET_OBJ_SHORT(obj):%s.\r\n",

  object.extra_flags = GET_OBJ_EXTRA(obj);
  /* etc, etc...Then notice the fwrite comming up.  It may be important. */

  if (fwrite(&object, sizeof(struct obj_file_elem), 1, fl) < 1) {
    perror("SYSERR: error writing object in Obj_to_store");
    return (0);
  logtest("   Reached end of Obj_to_store segment.\r\n");
  return (1);
Now, lets take a quick peek at what the logtest function generated for us...

 ** Crash_save -> About to initiate Obj_to_store
    Starting Obj_to_store.
Starting Object values in objsave.c Obj_to_store.
 ********** Finished object storing in objsave.c.
 Obj_ to_store: GET_OBJ_short(obj): a forged weapon handle.

 Well, that's it.  As you can see we get to the call just prior to
the strcpy call.  This means that right in there somewhere the code craps
out on me.  I am about to show you the logtest report with the strcpy
commented out...

 ** Crash_save -> About to initiate Obj_to_store
    Starting Obj_to_store.
Starting Object values in objsave.c Obj_to_store.
 ********** Finished object storing in objsave.c.
 Obj_ to_store: GET_OBJ_short(obj):
a forged weapon handle.
Copy is over.
 Obj_ to_store: GET_OBJ_SHORT(obj):
a forged weapon handle.
   Reached end of Obj_to_store segment.
 ** Crash_save -> Obj_to_store is over.  A 1 was returned to result.
For loop for containers is over.
 ** Crash_save -> About to leave if (obj) statement.
 ** Crash_save -> return true to calling statement.
Closing Socket in close_socket comm.c.

 See the "Copy is over." line?  That directly follows the strcpy
line which in this, Case B, is commented out.  And you can see the rest of
the stuff that travels afterwords.  The Closing Socket is just from this
being the result of a shutdown die command...etc.  So, the obvious problem
is that without the strcpy command the new title never gets pushed over to
the object.short_description to be saved.  I am at a loss as to why this
won't work.  Or should I say it will work when quiting but not when saving
or shuting down which really threw me.
 I *HOPE* I have provided enough information for all you gurus out
there. =)  I know we all hate to see "I had a segmentation fault error,
what do I do?" pop up on our screens.  Perhaps I've given you enough to get
me in the right direction.

Eagerly Awaiting,

P.S. Thanks in advance guys.  Anyone that got this far put in some time
reading. =) I hope there is enough here, I had to cut a lot out to make the
200 line maximum for a post. *sigh*

     | Ensure that you have read the CircleMUD Mailing List FAQ:  |
     |  http://qsilver.queensu.ca/~fletchra/Circle/list-faq.html  |

This archive was generated by hypermail 2b30 : 04/10/01 PDT