Re: [ Code ] Again... I still ahev problems with free() and NULL pointers Aug 04, 1997 at 09:52:50AM +0200

From: Eric Green (thrytis@IMAXX.NET)
Date: 08/04/97


On Aug 4, David Klasinc wrote
>
> Ok, I've done, what Sammy and George were suggesting and the result is,
> that still, nothing is working.. *grumble*

> Then I have this in my check_fall() where I check if ch is falling and
> since it's called every 2 seconds I've also put in few room spells that
> are supposed to take hp from char...
>
> void check_fall(void)
> {
>   int fall_dmg;
>   struct char_data *ch, *next_ch;
>   for (ch = character_list; ch; ch = next_ch) {
>     next_ch = ch->next;
>
>   if (ROOM_AFFECTED(IN_ROOM(ch), RAFF_ACID_RAIN))
>     gen_damage(ch, GET_MAX_HIT(ch) * 10 / 100, SPELL_ACID_RAIN);
>
>     if (ch && ((SECT(IN_ROOM(ch)) == SECT_FLYING)) && (!AFF_FLAGGED(ch, AFF_FLY
>         !(IS_NPC(ch) && MOB_FLAGGED(ch, MOB_WINGS)) &&
>         !(IS_NPC(ch) && MOB_FLAGGED(ch, MOB_NOACT)) &&
>         !(GET_LEVEL(ch) > LVL_IMMORT)) {
>
> .... etc etc etc ...

> Then there are usual checks, for the falling... as goes... first we check
> if ch is there... remember, we got in a syslog, that ch was set to NULL
> and that everything should work... Then we check if there is air in the
> room, if ch is maybe affected by flying, is this a mob with wings? and no
> act mobs (these are my dummy mobs, that just sit there with mobprogs
> hooked on them) and if ch is maybe immortal... Ok.. and mud crashes
> here...

Your FREE() macro is doing nothing for you here, because its another
level of the stack you're freeing at.

        void check_fail(...)
        {
          ...

            /* ch = 0x807ee85 */
            gen_damage(0x807ee85, ...);

Now, in gen_damage(), you have...

        gen_damage(ch, ...)
        {
          ...

          /* ch = 0x807ee85 */

          free(ch);
          ch = NULL;

          /* ch = 0x0 */

          ...
        }

(The actual free() and ch = NULL probably occur within a function called
by gen_damage(), but the effects are still the same.)

But now you return to the previous stack level, so ch is still the same
as before the gen_damage() call.

          /* ch = 0x807ee85 */
          if (ch && ((SECT(IN_ROOM(ch)) == SECT_FLYING)) && ...

And the game crashes.

If you still don't see why this is happening, consider a simpiler program
which does the same thing:

        void foo(int i)
        {
          i = 0;
        }

        void main()
        {
          int j = 10;

          foo(j);
          printf("%d\n", j);
        }

which should be obvious that it will print 10, because j is passed by value,
not by reference.

To fix your problem, you could have gen_damage() return a special value
indicating that the character has been freed.  In check_fall(), you would
test the return value, and return from check_fall() if the player died.

        if (ROOM_AFFECTED(IN_ROOM(ch), RAFF_ACID_RAIN))
            if (gen_damage(ch, GET_MAX_HIT(ch) * 10 / 100, SPELL_ACID_RAIN) < 0)
              return;

        if (ch && ((SECT(IN_ROOM(ch)) == SECT_FLYING)) && ...

Other solutions are throwing an exception in extract_char(), so the rest of
that function would be skipped, or moving extracted chars to a storage room
and freeing at the game_loop() level of the game.


Eric


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



This archive was generated by hypermail 2b30 : 12/08/00 PST