[Gambas-user] segfault with insanely large array of structures
Tobias Boege
taboege at ...626...
Mon Aug 12 11:29:32 CEST 2013
On Mon, 12 Aug 2013, Kevin Fishburne wrote:
> I know this code is horrible (it will be changed), but the following
> declarations and procedure raise a signal 11 and populate some of
> the array properties with non-zero values:
>
> ' Plan structures and array (server).
> Public Struct PlanBlockStructure ' Structure containing individual
> block data.
> Created As Boolean ' If block PWO has already been created.
> Skin As Short ' Block skin.
> HeightCurrent As Single ' Current height in feet of block.
> HeightTarget As Single ' Target height in feet of block.
> Grading As Boolean ' If grading is required.
> WorldX As Integer ' Hard coordinates of block once
> construction has been initiated.
> WorldY As Integer ' Hard coordinates of block once
> construction has been initiated.
> End Struct
> Public Struct PlanStructure ' Structure containing individual plan data.
> Block[300, 300] As Struct PlanBlockStructure
> Stage As Byte ' Current build stage (0 = design, 1 = clear
> and grade, 2 = wall construction, 3 = roofing construction, 4 =
> flooring construction, 5 = finished/maintenance).
> CurrentX As Short ' Current position in block array.
> CurrentY As Short ' Current position in block array.
> GradeTo As Single ' Elevation in feet to grade landscape to.
> CenterX As Integer ' Build site center coordinate.
> CenterY As Integer ' Build site center coordinate.
> End Struct
> Public Plan[2000] As Struct PlanStructure ' Architecutral plans.
>
> ' Plan maintenance (server).
> Public LastTime As Single = Timer ' Time last architectural plan was
> maintained.
>
> Public Sub Plan_Maintenance()
>
> ' Maintain architectural plans.
>
> ' General declarations.
> Dim Index As Short ' Plan to maintain.
> Dim Elevation As Integer ' Elevation of current tile in inches.
> Dim Excavation As Integer ' Number of inches to excavate to match
> specified grade.
>
> ' Check if plans are due to be updated.
> If Timer < (LastTime + 0.1) Then Return
> LastTime = Timer
>
> ' Cycle through plans.
> For Index = 0 To 1999
>
> ' Check if plan stage requires maintenance.
> If Plan[Index].Stage <> 0 Then
>
> ' Check plan stage.
> Select Case Plan[Index].Stage
>
> ' Clear and grade.
> Case 1
> ' Advance position in plan to next position requiring grading.
> Do Until Plan[Index].Block[Plan[Index].CurrentX,
> Plan[Index].CurrentY].Grading
> ' Increment X position in grid.
> Plan[Index].CurrentX += 1
> ' Check if X position needs wrapping.
> If Plan[Index].CurrentX >= 300 Then
> ' Wrap X position.
> Plan[Index].CurrentX = 0
> ' Increment Y position in grid.
> Plan[Index].CurrentY += 1
> ' Check if Y position needs wrapping.
> If Plan[Index].CurrentY >= 300 Then
> ' Advance to next stage.
> Plan[Index].Stage += 1
> Endif
> Endif
> Loop
> ' Clear snow and vegetation depths.
> Tiles.Depth_Assign_Snow(Plan[Index].Block[Plan[Index].CurrentX,
> Plan[Index].CurrentY].WorldX,
> Plan[Index].Block[Plan[Index].CurrentX,
> Plan[Index].CurrentY].WorldY, 0)
> Tiles.Depth_Assign_Vegetation(Plan[Index].Block[Plan[Index].CurrentX,
> Plan[Index].CurrentY].WorldX,
> Plan[Index].Block[Plan[Index].CurrentX,
> Plan[Index].CurrentY].WorldY, 0)
> ' Calculate hard elevation.
> Elevation =
> Tiles.Depth_Get_Hard(Plan[Index].Block[Plan[Index].CurrentX,
> Plan[Index].CurrentY].WorldX,
> Plan[Index].Block[Plan[Index].CurrentX,
> Plan[Index].CurrentY].WorldY)
> ' Calculate excavation amount.
> Excavation = Elevation - Plan[Index].GradeTo * 12
> ' Grade landscape.
> Tiles.Excavate(Plan[Index].Block[Plan[Index].CurrentX,
> Plan[Index].CurrentY].WorldX,
> Plan[Index].Block[Plan[Index].CurrentX,
> Plan[Index].CurrentY].WorldY, Excavation, True)
> ' Mark block as graded.
> Plan[Index].Block[Plan[Index].CurrentX,
> Plan[Index].CurrentY].Grading = False
>
> ' Wall construction.
> Case 2
>
> ' Roofing construction.
> Case 3
>
> ' Flooring construction.
> Case 4
>
> ' Finished/maintenance.
> Case 5
>
>
> End Select
>
> Endif
>
> Next
>
> End
>
> ' END OF CODE
>
> I attached the above code for better readability. It's notable that
> if the For...Next loop only addresses the first few indices of
> Plan[] that it works, which leads me to believe the array of
> structures is improperly allocated, probably due to its ridiculous
> size. The fact that some of the array property values read as
> non-zero before being assigned makes me think their pointers are
> pointing to out-of-process RAM being used by something else
> entirely. I suck at low-level programming so I'm just speculating
> ignorantly, sorry.
>
Have you tried to calculate your memory needs? Here's my attempt (the
occupied memory from Plan[2000] if we're just counting the Gambas variables
inside - if there was no memory overhead for Gambas variable maintenance
structures and other things):
$ pcalc "DEC=1 ((1+2+4+4+1+4+4)*300^2+1+2+2+4+4+4)*2000/1024^3"
3.35279
You are allocating 3.3 GiB... Well, this is particularly funny if you think
about it: _In case_ Gambas does not check a NULL return from malloc()
somewhere because this allocation fails, you could actually access valid
memory with a large enough offset into your array :-) However, you wouldn't
be able to access Plan[0] or generally low offsets. So this doesn't seem to
be the case here. If the allocation was successful, it is also impossible,
no matter how large the array is, that you get to read something you're not
supposed to read - at least on Linux.
A backtrace should clear this up, I think.
Regards,
Tobi
More information about the User
mailing list