Angband.oook.cz
Angband.oook.cz
AboutVariantsLadderForumCompetitionComicScreenshotsFunniesLinks

Go Back   Angband Forums > Angband > Development

Reply
 
Thread Tools Display Modes
Old August 5, 2009, 08:57   #1
Sergio
Scout
 
Join Date: Aug 2009
Posts: 26
Sergio is on a distinguished road
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];

	if (k_ptr->aware && (k_ptr->flags[2] & TR2_EASY_KNOW))
		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
File Type: zip Lorina.zip (12.1 KB, 247 views)
Sergio is offline   Reply With Quote
Old August 5, 2009, 09:35   #2
PowerDiver
Prophet
 
Join Date: Mar 2008
Posts: 2,712
PowerDiver is on a distinguished road
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?
PowerDiver is offline   Reply With Quote
Old August 5, 2009, 10:29   #3
Sergio
Scout
 
Join Date: Aug 2009
Posts: 26
Sergio is on a distinguished road
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 = '+';
			else if ((!object_flag_is_known(o_ptr, resists[i].set, resists[i].res_flag)) && (j < INVEN_TOTAL) && (o_ptr->k_idx)) sym = '?';
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 at 11:07.
Sergio is offline   Reply With Quote
Old August 5, 2009, 11:23   #4
PowerDiver
Prophet
 
Join Date: Mar 2008
Posts: 2,712
PowerDiver is on a distinguished road
Quote:
Originally Posted by Sergio View Post
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 = '+';
			else if ((!object_flag_is_known(o_ptr, resists[i].set, resists[i].res_flag)) && (j < INVEN_TOTAL) && (o_ptr->k_idx)) sym = '?';
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.
PowerDiver is offline   Reply With Quote
Old August 5, 2009, 11:27   #5
Nick
Vanilla maintainer
 
Nick's Avatar
 
Join Date: Apr 2007
Location: Canberra, Australia
Age: 52
Posts: 6,702
Donated: $60
Nick is on a distinguished road
Quote:
Originally Posted by Sergio View Post
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 Ring to rule them all, One Ring to find them,
One Ring to bring them all and in the darkness bind them.
Nick is offline   Reply With Quote
Old August 5, 2009, 18:21   #6
PowerDiver
Prophet
 
Join Date: Mar 2008
Posts: 2,712
PowerDiver is on a distinguished road
Quote:
Originally Posted by Nick View Post
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 at 18:28.
PowerDiver is offline   Reply With Quote
Old August 5, 2009, 19:36   #7
Sergio
Scout
 
Join Date: Aug 2009
Posts: 26
Sergio is on a distinguished road
Yes, moving the j < INVEN_TOTAL check did fix this, as suggested in the mailing list as well. Thanks all for your time
Sergio is offline   Reply With Quote
Old August 6, 2009, 02:12   #8
Zikke
Veteran
 
Join Date: Jun 2008
Location: Los Angeles
Posts: 1,061
Zikke is on a distinguished road
Quote:
Originally Posted by Sergio View Post
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:
Zikke is offline   Reply With Quote
Old August 6, 2009, 03:30   #9
Sergio
Scout
 
Join Date: Aug 2009
Posts: 26
Sergio is on a distinguished road
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!
Sergio is offline   Reply With Quote
Reply


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Quick(?) debug assist request (JBand) PaulBlay Development 2 June 17, 2009 22:21
Unangband debug commands? Donald Jonker Variants 3 March 5, 2009 04:08
Calling all maintainers: Debug command wishlist CunningGabe Vanilla 6 January 27, 2009 23:38
How to post character info Wraitheist Vanilla 3 August 20, 2008 17:48
monster list info DaviddesJ Vanilla 1 March 31, 2008 04:10


All times are GMT +1. The time now is 01:49.


Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2017, vBulletin Solutions, Inc.