1611: Character screen crash (space, h, or f), debug info included

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Sergio
    Scout
    • Aug 2009
    • 26

    1611: Character screen crash (space, h, or f), debug info included

    Hey. As I said in another thread, I compiled angband in debug mode and restarted angband until I could make the error happen. It's breaking in the line in bold:

    Code:
    bool easy_know(const object_type *o_ptr)
    {
    	object_kind *k_ptr = &k_info[o_ptr->k_idx];
    
    [B]	if (k_ptr->aware && (k_ptr->flags[2] & TR2_EASY_KNOW))[/B]
    		return TRUE;
    	else
    		return FALSE;
    }
    with the message Access Violation reading location 0x02131532, which happens to be inside k_ptr (k_ptr points to 0x021314f0). The address seems to be that of k_ptr->aware, but inside the debugger, I noticed that "&k_info[o_ptr->k_idx]" returns me an invalid instance. Since I'm no expert, I have no idea who fills k_info and when.

    I fail to see why the crash isn't consistent, though. I can help track this over IRC if you want (nick is Sergio100), I attached my savefile. I've been a professional C/C++ coder for over 10 years, and I've got a degree in CS, so don't be shy, talk dirty to me

    The call stack is:

    > angband.exe!easy_know(const object_type * o_ptr=0x02228338) Line 38 + 0x3 bytes C
    angband.exe!object_flag_is_known(const object_type * o_ptr=0x02228338, int idx=1, unsigned long flag=65536) Line 164 + 0x9 bytes C
    angband.exe!display_resistance_panel(const player_flag_record * resists=0x00500758, unsigned int size=12, const region * bounds=0x00500a28) Line 263 + 0x26 bytes C
    angband.exe!display_player_flag_info() Line 279 + 0x24 bytes C
    angband.exe!display_player(int mode=1) Line 912 C
    angband.exe!do_cmd_change_name() Line 195 + 0x9 bytes C
    angband.exe!textui_process_command(char no_request=0) Line 671 C
    angband.exe!textui_get_cmd(cmd_context context=CMD_GAME, char wait='') Line 1796 + 0x11 bytes C
    angband.exe!win_get_cmd(cmd_context context=CMD_GAME, char wait='') Line 4569 + 0xe bytes C
    angband.exe!cmd_get(cmd_context c=CMD_GAME, game_command * cmd=0x0017fe00, char wait='') Line 160 + 0xf bytes C
    angband.exe!process_command(cmd_context ctx=CMD_GAME, char no_request=0) Line 297 + 0x19 bytes C
    angband.exe!process_player() Line 1153 + 0x9 bytes C
    angband.exe!dungeon() Line 1487 C
    angband.exe!play_game() Line 1818 C
    angband.exe!WinMain(HINSTANCE__ * hInst=0x00400000, HINSTANCE__ * hPrevInst=0x00000000, char * lpCmdLine=0x00702f5c, int nCmdShow=1) Line 4890 C
    angband.exe!__tmainCRTStartup() Line 263 + 0x1b bytes C
    kernel32.dll!74f8e4a5()
    [Frames below may be incorrect and/or missing, no symbols loaded for kernel32.dll]
    ntdll.dll!76f3cfed()
    ntdll.dll!76f3d1ff()
    Attached Files
  • PowerDiver
    Prophet
    • Mar 2008
    • 2820

    #2
    I have a guess. Perhaps the variable k_info is being overwritten by some random pointer access.

    Can you check the value when it is set initially, line 641 in init2.c in r1610, and see if k_info has the same value when it crashes?

    Comment

    • Sergio
      Scout
      • Aug 2009
      • 26

      #3
      No, the address stays the same, both when it crashes and when it doesn't. I kept debugging (by making VS ignore the error line and go to the "return TRUE;" instead, and apparently it's only crashing for j = 36 in display_resistance_panel, which seems to be the player innate resistances (unless I'm interpreting the loop wrong). All the other items in that loop, from 24 (INVEN_WIELD) to 35 (INVEN_TOTAL-1), pass without error and can load their resist info fine.

      The call to the crashing function comes from display_resistance_panel@files.c:

      Code:
      			if (vuln) sym = '-';
      			else if (imm) sym = '*';
      			else if (res) sym = '+';
      [COLOR="Red"]			else if ((!object_flag_is_known(o_ptr, resists[i].set, resists[i].res_flag)) && (j < INVEN_TOTAL) && (o_ptr->k_idx)) sym = '?';[/COLOR]
      So, my question would be, why is the code calling that function when it's parsing the player resists? And why would you believe it doesn't crash every time?
      Last edited by Sergio; August 5, 2009, 10:07.

      Comment

      • PowerDiver
        Prophet
        • Mar 2008
        • 2820

        #4
        Originally posted by Sergio
        No, the address stays the same, both when it crashes and when it doesn't. I kept debugging (by making VS ignore the error line and go to the "return TRUE;" instead, and apparently it's only crashing for j = 36 in display_resistance_panel, which seems to be the player innate resistances (unless I'm interpreting the loop wrong). All the other items in that loop, from 24 (INVEN_WIELD) to 35 (INVEN_TOTAL-1), pass without error and can load their resist info fine.

        The call to the crashing function comes from display_resistance_panel@files.c:

        Code:
        			if (vuln) sym = '-';
        			else if (imm) sym = '*';
        			else if (res) sym = '+';
        [COLOR="Red"]			else if ((!object_flag_is_known(o_ptr, resists[i].set, resists[i].res_flag)) && (j < INVEN_TOTAL) && (o_ptr->k_idx)) sym = '?';[/COLOR]
        So, my question would be, why are we calling that function when we're parsing the player resists? And why would you believe it doesn't crash every time?
        That's a bug that is easily avoided by putting the "(j < INVEN_TOTAL) &&" before the function call rather than after it.

        The fact it did not crash every time is strange. Perhaps the order of placement of arrays created by C_ZNEW in the memory space is not fixed. Hopefully there is not some other bug randomly overwriting whatever structure comes after inventory.

        Comment

        • Nick
          Vanilla maintainer
          • Apr 2007
          • 9637

          #5
          Originally posted by Sergio
          No, the address stays the same, both when it crashes and when it doesn't. I kept debugging (by making VS ignore the error line and go to the "return TRUE;" instead, and apparently it's only crashing for j = 36 in display_resistance_panel, which seems to be the player innate resistances (unless I'm interpreting the loop wrong). All the other items in that loop, from 24 (INVEN_WIELD) to 35 (INVEN_TOTAL-1), pass without error and can load their resist info fine.
          OK, there's the answer - it's overrunning the end of the inventory array. There is no inventory[36], so it's just grabbing whatever it can find there and crashing if the entry in k_info is too silly.
          One for the Dark Lord on his dark throne
          In the Land of Mordor where the Shadows lie.

          Comment

          • PowerDiver
            Prophet
            • Mar 2008
            • 2820

            #6
            Originally posted by Nick
            OK, there's the answer - it's overrunning the end of the inventory array. There is no inventory[36], so it's just grabbing whatever it can find there and crashing if the entry in k_info is too silly.
            The strange thing is that he posted the pointers from the crash, and it appeared that the random o_ptr->k_idx that caused the problem is 0x532 - 0x4f0. I would have thought that was in bounds.
            [editing] that diff needs to be divided by size of an entry of course
            Last edited by PowerDiver; August 5, 2009, 17:28.

            Comment

            • Sergio
              Scout
              • Aug 2009
              • 26

              #7
              Yes, moving the j < INVEN_TOTAL check did fix this, as suggested in the mailing list as well. Thanks all for your time

              Comment

              • Zikke
                Veteran
                • Jun 2008
                • 1069

                #8
                Originally posted by Sergio
                Yes, moving the j < INVEN_TOTAL check did fix this, as suggested in the mailing list as well. Thanks all for your time
                Is this in a nightly? Or are you home-brewing
                A(3.1.0b) CWS "Fyren_V" NEW L:50 DL:127 A++ R+++ Sp+ w:The Great Axe of Eonwe
                A/FA W H- D c-- !f PV+++ s? d P++ M+
                C- S+ I- !So B ac++ GHB? SQ? !RQ V F:

                Comment

                • Sergio
                  Scout
                  • Aug 2009
                  • 26

                  #9
                  I was home-brewing at the time, but if you get the latest nightly as of this post (1621), it'll include the fix that Stefan O'Rear already posted

                  Thanks again for the fix!

                  Comment

                  Working...
                  😀
                  😂
                  🥰
                  😘
                  🤢
                  😎
                  😞
                  😡
                  👍
                  👎