Problem Need some advice on undefined behavior[SOLVED]

jedidia

shoemaker without legs
Addon Developer
Joined
Mar 19, 2008
Messages
10,842
Reaction score
2,105
Points
203
Location
between the planets
NOTE: The problem was more like undefined behavior by my brain than by my program...



I have undefined behavior, and it's possibly happening in oapiReadScenario_nextline(). I have trouble believing that, since it's a fairly often used function, so I'd like to have some thoughts on the matter before bothering martin.
As the behavior is undefined, it would be really difficult to reproduce outside of my code I imagine (I could provide the code if wanted, but only in its entirety, you'll see below why). I'm using oapiReadScenario_nextline() a lot (obviously), and only in one particular place does it cause trouble, and only under certain circumstances.

Here's the deal:

I'm reading through some scenario lines until the end of one of my blocks is reached. If I read those lines, the vessel ends up sitting on the sun. If I don't read them, it doesn't.

If I read only one line in that place, it's ok. If I read more than one lines in that particular place, the problem appears. I later read in other lines, of course, which again don't seem to cause any trouble. But reading two lines in this particular place wreaks havoc.

I want to emphasise that I threw out any other code that would get executed. Even the comparisons. I narrowed down the problem to just running a loop and reading in two lines in that function, and trouble starts happening. The function looks like this currently, but that won't be any help in finding the cause, I'm afraid. It is really sensitive and even slight changes to the function can make it go away.

Code:
bool IMS_ModuleFunction_Base::LoadState(FILEHANDLE scn)
{
	char *line;
	int lines = 0;
	while ((oapiReadScenario_nextline(scn, line)))
	{
		if (lines == 2)
		{
			break;
		}
		lines++;
	}
	return true;
}


Changing the function like this already avoids the problem:

Code:
bool IMS_ModuleFunction_Base::LoadState(FILEHANDLE scn)
{
	char *line;
	for (int i = 0; i < 2; ++i)
	{
		oapiReadScenario_nextline(scn, line);
	}
	return true;
}

The parsed lines look like this (very unspectacular)

Code:
deploy 0.126362 1
END_MODULEFUNC

The entire scenario looks like this:
Code:
BEGIN_DESC
Current scenario state


Contains the latest simulation state.
END_DESC

BEGIN_ENVIRONMENT
  System Sol
  Date MJD 51982.5301192178
  Help CurrentState_img
END_ENVIRONMENT

BEGIN_FOCUS
  Ship stack
END_FOCUS

BEGIN_CAMERA
  TARGET stack
  MODE Extern
  POS 3.450535 32.801834 -16.759016
  TRACKMODE TargetRelative
  FOV 50.00
END_CAMERA

BEGIN_HUD
  TYPE Surface
END_HUD

BEGIN_MFD Left
  TYPE Orbit
  PROJ Ship
  FRAME Ecliptic
  REF Earth
END_MFD

BEGIN_MFD Right
  TYPE Surface
  SPDMODE 1
END_MFD

BEGIN_SHIPS
ISS:ProjectAlpha_ISS
  STATUS Orbiting Earth
  RPOS -2990021.017 5934691.266 -1095620.989
  RVEL 6750.5867 2995.5807 -2153.4958
  AROT 30.000 0.000 50.000
  AFCMODE 7
  IDS 0:588 100 1:586 100 2:584 100 3:582 100 4:580 100
  NAVFREQ 0 0
  XPDR 466
END
Mir:Mir
  STATUS Orbiting Earth
  RPOS -4813607.970 282220.141 4614324.376
  RVEL -5354.1155 -340.0731 -5560.1332
  AROT 0.000 -45.000 90.000
  AFCMODE 7
  IDS 0:540 100 1:542 100 2:544 100
  XPDR 482
END
Luna-OB1:Wheel
  STATUS Orbiting Moon
  RPOS 975512.246 2014098.250 215.576
  RVEL -1331.9280 645.0975 0.2975
  AROT 0.000 0.000 -152.600
  AFCMODE 7
  IDS 0:560 100 1:564 100
  XPDR 494
END
GL-01:DeltaGlider
  STATUS Orbiting Earth
  RPOS 4085465.294 4047422.464 -3123397.525
  RVEL 6230.7601 -3857.6108 2984.9737
  AROT -52.670 -56.929 90.320
  AFCMODE 7
  PRPLEVEL 0:0.553000 1:0.900000
  NAVFREQ 0 0 0 0
  XPDR 0
  HOVERHOLD 0 1 0.0000e+000 0.0000e+000
  AAP 0:0 0:0 0:0
END
SH-03:ShuttleA
  STATUS Landed Earth
  BASE Habana:4
  POS -82.3982414 23.0005396
  HEADING 70.00
  ALT 2.912
  AROT 50.119 -65.937 19.478
  AFCMODE 7
  PRPLEVEL 0:1.000000 1:1.000000
  NAVFREQ 0 0
  XPDR 0
  PODANGLE 0.0000 0.0000
  DOCKSTATE 0 0.0000
  AIRLOCK 0 0.0000
  GEAR 0 0.0000
  PAYLOAD MASS 0.0 0
  ATTREF 0 0 0
  ADI_LAYOUT 0
END
PB-01:ShuttlePB
  STATUS Landed Earth
  BASE Habana:1
  POS -82.4000000 22.9994604
  HEADING 22.00
  ALT 1.496
  AROT 64.386 -18.865 7.402
  AFCMODE 7
  PRPLEVEL 0:1.000000
  NAVFREQ 0 0
END
GL-02:DeltaGlider
  STATUS Landed Mars
  BASE Olympus:3
  POS -135.4300000 12.7366196
  HEADING 0.00
  ALT 2.532
  AROT 81.111 -8.915 -44.736
  AFCMODE 7
  PRPLEVEL 0:1.000000 1:1.000000
  NAVFREQ 0 0 0 0
  XPDR 0
  HOVERHOLD 0 1 0.0000e+000 0.0000e+000
  GEAR 1 1.0000
  AAP 0:0 0:0 0:0
END
SH-01:ShuttleA
  STATUS Landed Moon
  BASE Brighton Beach:1
  POS -33.4375000 41.1184067
  HEADING 0.00
  ALT 3.027
  AROT 64.274 33.319 48.978
  AFCMODE 7
  PRPLEVEL 0:1.000000 1:1.000000
  NAVFREQ 0 0
  XPDR 0
  PODANGLE 0.0000 0.0000
  DOCKSTATE 0 0.0000
  AIRLOCK 0 0.0000
  GEAR 0 0.0000
  PAYLOAD MASS 0.0 0
  ATTREF 0 0 0
  ADI_LAYOUT 0
END
stack:IMS2\BP101_SOLAR_PANEL
MODULE_BEGIN_0
  FILE IMS2\BP101_SOLAR_PANEL.cfg
  PDR 0,0,0 0,0,1 0,1,0
  IMSATT 1 0
  IMSATT 1 0
BEGIN_MODULEFUNC 0
deploy 0.126362 1
END_MODULEFUNC
END_BASE_ATTRIB
MODULE_END
  COG 0.000000 0.000000 0.000000
  STATUS Orbiting Earth
  RPOS 7005832.935 6.637 188748.601
  RVEL -207.7308 0.2711 7529.0671
  AROT 0.000 -0.000 0.000
  AFCMODE 7
  NAVFREQ 0 0
END
END_SHIPS

Also, there is nothing wrong with the lines when I look at them when they are parsed in in the debugger.

The major question I have at this time is, what are possible causes that don't involve an overflow in oapiReadScenario_nextline(), because frankly I can't imagine to be the first to stumble on something like that.
I know you won't be able to tell anything concrete, because no code, and no code because code is extensive. Just the conceptual level. Currently I'm having trouble thinking of anything on my part that could cause this behavior triggered by two calls to oapiReadScenario_nextline() in a certain place. It's a loading operation, so all I do is parsing, I have zero potentially unsafe operations like printfs or array resizings going on. There are some sscanf calls that fill ints and doubles, of course. Can an sscanf call writing to a wrong type cause overflow? That's about the only possibility on my end I could currently think of.
 
Last edited:

jedidia

shoemaker without legs
Addon Developer
Joined
Mar 19, 2008
Messages
10,842
Reaction score
2,105
Points
203
Location
between the planets
:censored: :facepalm:

Yes, I am. Since the behavior produced is exactly the same as with the code that should actually work, it sheds some light on where the bug occurs. I'll check back with new info as soon as I run some tests. During programming class, while learning about black- and whitebox tests. How very appropriate :lol:

---------- Post added at 07:20 AM ---------- Previous post was at 07:07 AM ----------

Ok, I'm a moron:

Code:
while (oapiReadScenario_nextline(scn, line) && readblock)
{
    if (!strnicmp(line, "END_MODULEFUNC", 14))
    {
 	readblock = false;
    }
}

Will parse another line after readblock has switched to false. readblock must be checked first:

Code:
while (readblock && oapiReadScenario_nextline(scn, line))
{
    if (!strnicmp(line, "END_MODULEFUNC", 14))
    {
  	readblock = false;
    }
}

Since I know that I wrote this similar in other places in the code, I'm really, really surprised that it didn't shoot me in the foot earlier (well, phantom foot. I shot my legs of a long time ago). Now to go back over it and find out why it didn't shoot me in the foot earlier... :shifty:
 

martins

Orbiter Founder
Orbiter Founder
Joined
Mar 31, 2008
Messages
2,448
Reaction score
462
Points
83
Website
orbit.medphys.ucl.ac.uk
Alternatively you could just say
Code:
while (oapiReadScenario_nextline(scn, line) && strnicmp(line, "END_MODULEFUNC", 14)
{
  // parse line
}
 

jedidia

shoemaker without legs
Addon Developer
Joined
Mar 19, 2008
Messages
10,842
Reaction score
2,105
Points
203
Location
between the planets
Heh, didn't think of that. Very readable with the end tag clearly visible in the loop header.
 
Top