Why am I getting segfaults when doing `foreach` with arrays of references?
Liam McGillivray
yoshi.pit.link.mario at gmail.com
Sat Mar 9 06:29:45 UTC 2024
With [my game project](https://github.com/LiamM32/Open_Emblem), I
have been getting segmentation faults that are unexplainable at
my knowledge level. They seem to happen when doing a "foreach"
loop through an array of references.
Skip to the bolded text if you don't want to read too much, as I
found a way around the first example.
Prior to the latest commit, I had this "foreach" loop lines
starting at `oe-raylib/source/mission.d:214` ([see
file](https://github.com/LiamM32/Open_Emblem/blob/09505794970168c68ed5cffd9aa2ed69490ee80e/oe-raylib/source/mission.d)). It would segfault on the second line shown here:
```
foreach (startTile; this.startingPoints) {
startTile.occupant.map = this;
writeln("Just assigned Unit.map to the Mission
object.");
this.factionUnits["player"] ~= *startTile.occupant;
}
```
This was in the `Mission` class (a derivative of `Map`), which
`this` would be a reference to. `startTile` is an instance of the
`GridTile` struct, which contains a reference to a `Tile` object
called `tile`. The `Tile` object had a pointer to a `Unit` object
called `occupant`. `GridTile.occupant` is a convenience function
that's equivalent to `GridTile.tile.occupant`. Finally, the
`Unit` class contains a reference to a `Map` object called `map`.
Because `Mission` is a derived class, a `Mission` object can also
fit. All of the things being accessed were public.
I thought the problem was that it was looking in `Tile` objects
with `occupant` being null, but changing line 214 to the
following didn't solve it.
```
foreach (startTile; this.startingPoints) if
(startTile.occupant !is null) {
```
**Current example**
I ended up getting rid of that line causing the segmentation
fault and achieving the desired functionality a different way,
but now I get a similar one later in the program.
The `turnReset` function in my [`Map`
class](https://github.com/LiamM32/Open_Emblem/blob/master/source/map.d) does a 'foreach' loop through an array of `Unit` objects:
```
void turnReset() {
foreach(unit; this.allUnits) {
unit.turnReset;
}
}
```
My program successfully completed one cycle of the loop, but
segfaulted with the second one. I found in GDB that for the
second object it didn't even reach the first line in
`Unit.turnReset()`. This may imply that the array length of
`Map.allUnits` is more than one, but no object has been assigned
to `allUnits[1]`. However, there are no lines anywhere in my code
that changes the length of this array without appending. I tried
doing the `grep -r allUnits` command to look for every mention of
this array in my code, and here is what I have:
```
source/map.d: public Unit[] allUnits;
source/map.d: foreach (unit; this.allUnits) {
source/map.d: foreach(unit; this.allUnits) {
source/map.d: assert (canFind(map.allUnits, unit));
source/unit.d: if (this in map.allUnits) {
oe-raylib/source/mission.d: this.allUnits ~=
*startTile.occupant;
oe-raylib/source/mission.d: foreach (unit; this.allUnits) {
oe-raylib/source/mission.d: if (addToMap) allUnits ~=
newUnit;
oe-raylib/source/mission.d: foreach (unit; mission.allUnits) {
oe-raylib/source/mission.d.bak2: foreach (unit;
this.allUnits) {
```
As far as I see, there's no way that the `allUnits` array would
be longer than the number of objects that have been added to it,
so why would calling a public function of one of it's members
cause a segfault?
More information about the Digitalmars-d-learn
mailing list