|
Post by felixp7 on Oct 25, 2019 9:16:17 GMT 1
So, for all I know this is a known bug that was fixed in recent versions of BaCon, but I don't have my other machine handy to test; apologies in advance if that's the case.
Check out this little test program:
OPTION BASE 1
CONST max_ships = 20
RECORD sector[8][8] LOCAL scanned LOCAL energy END RECORD
RECORD ship[max_ships] LOCAL energy LOCAL shields LOCAL max_e LOCAL max_s LOCAL galaxy_x LOCAL galaxy_y LOCAL sector_x LOCAL sector_y END RECORD
FOR i = 1 TO max_ships PRINT i, ": ", ship[i].galaxy_x, "x", ship[i].galaxy_y, " "; NEXT PRINT
FOR y = 1 TO 8 FOR x = 1 TO 8 sector[y][x].scanned = FALSE sector[y][x].energy = 1000 NEXT NEXT
FOR i = 1 TO max_ships PRINT i, ": ", ship[i].galaxy_x, "x", ship[i].galaxy_y, " "; NEXT PRINT
You'd expect the `ship` array elements to have the same values before and after initializing the `sector` array, right? Since they're not aliased or anything. But they don't; the last few sectors apparently overlap with the first ship and change. In the game where this is from, the overlap appears to be 5 sectors in length; I didn't want to make the test program too long.
So, what's going on here? Am I making an obvious beginner's mistake? Or is it a compiler bug? I'm running BaCon 3.7.2 with GCC 7.3.0 as back-end, on a 64-bit machine. Thank you!
Update: turns out the bug only manifests under OPTION BASE 1.
|
|
|
Post by bigbass on Oct 25, 2019 18:52:43 GMT 1
Hello felixp7
I was getting the same result whatever I tried then thought to use WHILE WEND and the problem is somewhere caused by FOR NEXT in memory
this "seems" to work on the surface for me but you would have to see if it would work for you together with the logic you need
I'm using the latest bacon tested with gcc and clang
joe
OPTION BASE 1
'OPTION COLLAPSE TRUE
CONST max_ships = 20 CONST max_sector = 8
RECORD sector[max_sector][max_sector] LOCAL scanned LOCAL energy END RECORD
RECORD ship[max_ships] LOCAL energy LOCAL shields LOCAL max_e LOCAL max_s LOCAL galaxy_x LOCAL galaxy_y LOCAL sector_x LOCAL sector_y END RECORD
x = 1 y = 1 WHILE y <= 8 WHILE x <= 8 sector[y][x].scanned = FALSE sector[y][x].energy = 1000 INCR x WEND INCR y WEND
PRINT "________ships____________________________________" FOR i = 1 TO max_ships PRINT i, ": ", ship[i].galaxy_x, "x", ship[i].galaxy_y, " "; NEXT PRINT
PRINT "--- record sector-------" PRINT sector[1][1].scanned PRINT sector[1][1].energy
PRINT "________ships after_______________________________" FOR i = 1 TO max_ships
PRINT i, ": ", ship[i].galaxy_x, "x", ship[i].galaxy_y, " "; NEXT PRINT
________ships____________________________________ 1: 0x0 2: 0x0 3: 0x0 4: 0x0 5: 0x0 6: 0x0 7: 0x0 8: 0x0 9: 0x0 10: 0x0 11: 0x0 12: 0x0 13: 0x0 14: 0x0 15: 0x0 16: 0x0 17: 0x0 18: 0x0 19: 0x0 20: 0x0 --- record sector------- 0 1000 ________ships after_______________________________ 1: 0x0 2: 0x0 3: 0x0 4: 0x0 5: 0x0 6: 0x0 7: 0x0 8: 0x0 9: 0x0 10: 0x0 11: 0x0 12: 0x0 13: 0x0 14: 0x0 15: 0x0 16: 0x0 17: 0x0 18: 0x0 19: 0x0 20: 0x0
------------------ (program exited with code: 0) Press return to continue
|
|
|
Post by felixp7 on Oct 25, 2019 19:25:22 GMT 1
That's very interesting! So either moving to OPTION BASE 0 (changing the limits accordingly) or using WHILE loops instead of FOR works equally well. Good to know! I'm leaning towards the former option though, it's a little more work but would also solve another unrelated problem with the larger program. Thank you very much!
|
|
|
Post by bigbass on Oct 26, 2019 5:23:52 GMT 1
Hello felixpz
I like that you are posting your code in steps thanks
and I was puzzled with the output not returning the expected values
and I moved the order of the RECORDS and it works now I don't get it something is strange
*personally with arrays I start counting with zero but it should work starting with one also
I just try to debug and get it to compile and run what's happening during the conversion I have no clue
Joe
RECORD ship[max_ships] LOCAL energy LOCAL shields LOCAL max_e LOCAL max_s LOCAL galaxy_x LOCAL galaxy_y LOCAL sector_x LOCAL sector_y END RECORD
RECORD sector[8][8] LOCAL scanned LOCAL energy END RECORD
|
|
|
Post by felixp7 on Oct 26, 2019 6:52:34 GMT 1
The memory area that gets overwritten, that's what changes. I tried swapping the declarations like you said, and now I get a segfault while initializing the sector array. Your C compiler probably lays them out differently in memory.
On a whim, I also tried to invert what I do in the code, initializing the ships and reading the sectors instead:
OPTION BASE 1
CONST max_ships = 20
RECORD ship[max_ships] LOCAL energy LOCAL shields LOCAL max_e LOCAL max_s LOCAL galaxy_x LOCAL galaxy_y LOCAL sector_x LOCAL sector_y END RECORD
RECORD sector[8][8] LOCAL scanned LOCAL energy END RECORD
FOR y = 1 TO 8 FOR x = 1 TO 8 PRINT " ", sector[y][x].scanned; PRINT ",", sector[y][x].energy; NEXT PRINT NEXT
FOR i = 1 TO max_ships ship[i].energy = 3000 ship[i].sector_y = 7 NEXT PRINT
FOR y = 1 TO 8 FOR x = 1 TO 8 PRINT " ", sector[y][x].scanned; PRINT ",", sector[y][x].energy; NEXT PRINT NEXT
And... now they don't seem to overlap anymore, BUT the sectors clearly overlap with some other memory area. Likely whatever comes right after them, which now happens to be code. And I bet it has something to do with the fact that `sector` is multidimensional.
Edit: in fact it seems to be a problem with multidimensional arrays of records specifically. I have another array in my game with no less than 4 dimensions, and it seems to work just fine. The difference? It's declares as:
GLOBAL galaxy[8][8][8][8] In other words, a simple numeric array. And I know BaCon treats some kinds of arrays differently.
|
|
|
Post by Pjot on Oct 26, 2019 14:11:21 GMT 1
Hi felixp7, Thanks for your post! I am not sure if this could be called a bug, because there are historic reasons why it was implemented like this. But at least it is inconsistent and undocumented. Therefore, I made sure that declarations of RECORDs (static and dynamic) now also do obey to OPTION BASE. I will do some more testing with existing programs to see if everything keeps working. But all of my preliminary tests seem to be fine. If you fetch the latest beta then your issue should not occur anymore (tested both with GCC and CLang). BR Peter
|
|
|
Post by felixp7 on Oct 26, 2019 15:05:12 GMT 1
I just checked the docs again. You're right, the section on arrays of records doesn't mention they were supposed to ignore OPTION BASE all along. Oh well. Ironically, I just finished converting my game logic to work with OPTION BASE 0. In fact I'll update the other thread in a moment. This fix should prove very useful in the future however. Thank you so much!
|
|