Program crashes on string manipulation
BlitzMax Forums/Brucey's Modules/Program crashes on string manipulation
| ||
I have a routine that is parsing a bitmapfont definition file with lots of strings such as:char id=33 x=2 y=2 width=3 height=12 xoffset=1 yoffset=3 xadvance=5 page=0 chnl=15 using local sections:String[] = lines[i].Split(" ") local parms:String[] = sections[0].Split("=") I have if statements checking to see if sections and parms are populated (Length > 0) before accessing elements. The program crashes with an exception_access_violation error IF I use sdl.gl2sdlmax2d, brl.d3d9max2d, or srs.d3d11max2d. It will execute cleanly if I use brl.glmax2d. I'm using bcc v. 0.84, bmk v. 3.16; compiling 64 bit on Windows 10. Any thoughts? |
| ||
Additional info: Occasionally it will give me debugging information. When it does, the sections variable shows as null in the debugger and the program line highlighted is passed 2 different checks to see if sections is populated with elements. Here is the full loop for review: Local contents:String Try contents = LoadText("res/fonts/" + name + ".fnt") Catch err:TStreamReadException RuntimeError("Read Exception: " + err.ToString()) End Try Local lines:String[] = contents.Split("~n") contents = Null Local numGlyphs:Int, index:Int = 0 Local txWidth:Float, txHeight:Float For Local i:Int = 0 Until lines.Length lines[i] = lines[i].Trim() lines[i] = lines[i].Replace("~r", "") Local sections:String[] = lines[i].Split(" ") If (sections.Length < 1) DebugStop() EndIf Select sections[0] Case "common" Local parms:String[] = sections[1].Split("=") lineHeight = Float(parms[1]) Case "page" Local parms:String[] = sections[2].Split("=") Local texFileName:String = parms[1].Replace("~q", "") texture = LoadImage("res/fonts/" + texFileName) If (texture = Null) RuntimeError("Error loading font texture file " + texFileName) EndIf Case "chars" Local parms:String[] = sections[1].Split("=") numGlyphs = Int(parms[1]) glyphs = New Glyph[numGlyphs] Case "char" If (sections.Length < 9) DebugLog("Error parsing line " + sections[0]) Continue EndIf Local id:Int = Int(GetValue(sections[1])) If (id < 32) Continue EndIf If (id < minId) minId = id ElseIf (id > maxId) maxId = id EndIf If (index = glyphs.length) RuntimeError("BitmapFont New: more glyphs than " + numGlyphs) EndIf glyphs[index] = New Glyph glyphs[index].id = id glyphs[index].x = Int(GetValue(sections[2])) <-- typically where the debugger might kick in glyphs[index].y = Int(GetValue(sections[3])) glyphs[index].width = Int(GetValue(sections[4])) glyphs[index].height = Int(GetValue(sections[5])) glyphs[index].xOffset = Float(GetValue(sections[6])) glyphs[index].yOffset = Float(GetValue(sections[7])) glyphs[index].advance = Float(GetValue(sections[8])) index :+ 1 End Select Next |
| ||
FYI: Glyph is a Type with the following definition:Type Glyph Field id:Int Field x:Float, y:Float Field width:Float, height:Float Field xOffset:Float, yOffset:Float Field advance:Float End Type And unfortunately the error is now consistent no matter which graphics driver I select. :\ |
| ||
Unfortunately the error is now consistent no matter which graphics driver I select. :\ I'd actually class that as fortunate :-) Intermittent bugs are the worse to find, consistent bugs are much 'easier' by comparison. Have you tried the same code with the legacy 'Max compiler? |
| ||
Thanks, Col. Putting the code in legacy yielded more debug info. The last line of the file was not being processed correctly making the last array element null. So there you go. Now it runs in NG without issue. Thanks!! But that raises a question about the NG debugger: it doesn't seem to catch what it should. Too bad, I have been programming for NG and some of my code doesn't run in legacy. Is that something that is planned on being fixed / updated? |
| ||
Cool that you got it fixed. If you have raised an issue within the repo itself then Brucey is pretty hot on fixing things up so, at a guess, I'd say yes it will be fixed. |
| ||
I've tested the max legacy code in NG and it runs without issues no matter what graphics driver and I've applied NG method overloading back to the classes (Types) without issue as well. I think where I get into trouble is with Structs. I originally created Structs for small classes like 2D Vectors, and Color class and a Glyph class for bitmap font definitions. When I use Structs, I get odd errors that are hard to pin down. If I stick with Types only I can run the code without issues. So how / when do you use them correctly? |
| ||
Hallo, is it possible to provide a small working example which shows the issue you were having? Things to note about Struct - since it is not a "pointer" to data, a test for Null-ness is invalid - because a Struct can never be Null. On initialisation, all the fields of a Struct will be zeroed (unless you have a constructor which does otherwise). An array of Structs is basically a single block of memory where every x bytes represents the content of the next Struct - whereas an array of Types, is just a list of Object references/pointers. Used in the right context, small Structs are far more efficient than creating/collecting similar amounts of Types/Objects. |