You are not logged in.
While running a debug build of OpenSonic on Visual Studio .NET 2003 (or any version with assertions enabled) I get a crash when some dialogs appear in the game. It looks like this:
Debug Assertion Failed!
Program: C:\dev\opensnc15\opensonic\trunk\opensonic.exe
File: isctype.c
Line: 68Expression: (unsigned)(c + 1) <= 256
On my setup, it appears that the library function isspace() prefers an unsigned char. I went ahead and added an (unsigned char) cast to the isspace() call in fix_wordwrap() and to the other isspace() call in expand_variables() which seemed to solve the problem.
A specific patch for font.c is available here. There are other isspace() calls outside that file that probably should be cast as well, referencing this article I came across while researching this bug. However, I don't know enough to say whether this solution is appropriately cross-platform.
Last edited by Celdecea (2009-03-08 18:58:48)
Offline
The standard prototype of the isspace function is:
int isspace(int ch)please see here: http://www.cplusplus.com/reference/clib … space.html
The current source code (which uses char) is compatible with the standards (please see the above link). The following characters are considered white spaces*:
' ' (0x20) space (SPC)
'\t' (0x09) horizontal tab (TAB)
'\n' (0x0a) newline (LF)
'\v' (0x0b) vertical tab (VT)
'\f' (0x0c) feed (FF)
'\r' (0x0d) carriage return (CR)Note that 0 <= c <= 127 for any character c in the table. isspace(c) returns true (ie, != 0) if c is one of the above characters (or false otherwise).
Can you please send the texts that appear in the dialog boxes which make the game crash? Does the problem happen in the Release build?
Since the current code is compatible with the standards, we must figure out why this problem happened in MSVC. This is important for the translation module, which should be implemented soon.
EDIT*: maybe a setlocale(LC_ALL, "C") or setlocale(LC_CTYPE, "C") should be included somewhere in the code (in the beginning of the game) ?
Last edited by Alexandre (2009-03-09 22:08:26)
Offline
Possibly compiler-specific. Read on:
With assertions enabled the very first dialog in the tutorial will crash the game, but not in the release build since assertions are typically disabled. When tracing it down, the crash occurs after $PLAYER_SONIC is turned to a \200 in get_variable(), which is 128 decimal and -128 if it was a signed char. The isspace() call has an assertion check for such numbers.
Here is a screenshot of the crash:
msvcr71d.dll!_chvalidator_mt(threadlocaleinfostruct * p=0x1027c618, int c=-128, int mask=8) Line 68 + 0x2a C
msvcr71d.dll!isspace(int c=-128) Line 133 + 0x2f C
opensonic.exe!fix_wordwrap(char * str=0x059b72d4, int minlength=22, int maxlength=29) Line 318 + 0x12 C
opensonic.exe!font_set_text_wordwrap(font_t * f=0x059b72d0, int minlength=22, int maxlength=29, char * fmt=0x0048c680, ...) Line 152 + 0x14 C
opensonic.exe!level_call_dialogbox(char * title=0x0048c600, char * message=0x0048c680) Line 1989 + 0x17 C
opensonic.exe!update_dialogregions() Line 2835 + 0x24 C
opensonic.exe!level_update() Line 830 C
opensonic.exe!_mangled_main(int argc=2, char * * argv=0x003e3e38) Line 193 + 0xb C
alleg42.dll!1007135d()
opensonic.exe!WinMain(void * hInst=0x00400000, void * hPrev=0x00000000, char * Cmd=0x000423b3, int nShow=10) Line 246 + 0x21 C
opensonic.exe!WinMainCRTStartup() Line 390 + 0x39 C
kernel32.dll!7c817067()
It is clear that isspace() is being called with -128 in this case, which isctype.c does not like. Two machines with identical setups can reproduce this, but it looks to be specific to the libraries used by MSVC 2003. Until recently I just did the release build and ignored it but I don't always remember after doing fresh checkouts. I find more questions than answers here and here. Possible help here.
I will see what I can come up with as a better cross-platform solution (aside from using #ifdef .. #undef tricks).
Offline
Oh, I see. The $PLAYER_SONIC string is replaced by the '\200' character which is used to show that little sonic emoticon in the dialogs.
I will see what I can come up with as a better cross-platform solution (aside from using #ifdef .. #undef tricks).
A simple macro in util.h should do the trick:
...
/* Useful macros */
#define randomize() (srand(time(NULL)))
#define random(n) ((int)(((double)rand() / ((double)(RAND_MAX)+(double)(1)))*(n)))
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
#define round(x) ((int)(((x)>0.0)?((x)+0.5):((x)-0.5)))
#define clip(val,a,b) ( ((val)<min((a),(b))) ? min((a),(b)) : ( ((val)>max((a),(b))) ? max((a),(b)) : (val) ) )
#define swap(a,b) swap_ex(&(a), &(b), sizeof(a))
#define is_whitespace(c) ((c)==' '||(c)=='\t'||(c)=='\n'||(c)=='\v'||(c)=='\f'||(c)=='\r')...
Then we can replace all the isspace() calls (4 in total - 2 in font.c and 2 in util.c) by our new macro. ![]()
(... or we can just use other character <= 127 to display the Sonic/Tails/Knuckles emoticons)
Probably there are other cross-platform solutions too.
Offline
After more research I found out you were right: http://www.ime.usp.br/~pf/algoritmos/au … space.html . Sorry about that.
Although I have never seen any problems with gcc, we should use the standard routines as much as we can, otherwise we can end up with an inconsistent code (isspace() and is_whitespace() mixed in the code).
I'm using your solution now: isspace( (unsigned char)*p ). ![]()
Offline
Either way, problem appears solved as of revision 18. ![]()
Offline