ygrenier/SwissEphNet

NULL deref when using JPL ephemeris

Closed this issue · 6 comments

Hi,

I recently started using SwissEph. I love that it is so powerful. But using JPL ephemeris, I am getting a null deref exception:

        public int swi_pleph(double et, int ntarg, int ncent, CPointer<double> rrd, ref string serr) {
            int i, retc;
            Int32[] list = new Int32[12];
            double[] pv = js.pv;    <<<<<< js is null. 

I solved the problem by commenting out
js = null
in swi_close_jpl_file(); Obviously this is hacky, and I am curious about what the root cause is. What is the real fix here?

Here is my test app:

using SwissEphNet;
using System;
using System.Text.RegularExpressions;

namespace SweMini
{
	class Program
	{
		static int Main(string[] args)
		{
			string sdate = String.Empty, serr = String.Empty;
			int jday = 1, jmon = 1, jyear = 2000;
			double jut = 0.0;
			using (var swe = new SwissEph())
			{
				swe.swe_set_ephe_path(@"X:\Projects\Swiss\jplfiles");
				swe.swe_set_jpl_file("de430.eph");
				swe.OnLoadFile += swe_OnLoadFile;

				while (true)
				{
					Console.Write("\nDate (d.m.y) ? ");
					sdate = Console.ReadLine();
					if (String.IsNullOrWhiteSpace(sdate))
						break;
					
					/*
                     * stop if a period . is entered
                     */
					if (sdate == ".")
						return SwissEph.OK;
					var match = Regex.Match(sdate, @"(\d+)\.(\d+)\.(\d+)");
					if (!match.Success)
						continue;
					jday = int.Parse(match.Groups[1].Value);
					jmon = int.Parse(match.Groups[2].Value);
					jyear = int.Parse(match.Groups[3].Value);

					/*
                     * we have day, month and year and convert to Julian day number
                     */
					var jd = swe.swe_julday(jyear, jmon, jday, jut, SwissEph.SE_GREG_CAL);

					double[] pos = new double[] { 0, 48, 0 };
					double risetime = 0;
					swe.swe_rise_trans(
						jd,
						SwissEph.SE_MOON,
						null,
						SwissEph.SEFLG_JPLEPH,
						SwissEph.SE_CALC_SET,
						pos,
						1013.25,
						20,
						ref risetime,
						ref serr);

					int year = 0, month = 0, day = 0, hour = 0, minute = 0;
					double second = 0;
					swe.swe_jdet_to_utc(risetime, SwissEph.SE_GREG_CAL,
						ref year, ref month, ref day, ref hour, ref minute, ref second);
					Console.WriteLine($"{year}/{month}/{day} {hour}:{minute}:{second}");
				}
			}

			return 0;
		}
		
		static void swe_OnLoadFile(object sender, LoadFileEventArgs e)
		{

			var f = e.FileName;
			if (System.IO.File.Exists(f))
				e.File = new System.IO.FileStream(f, System.IO.FileMode.Open, System.IO.FileAccess.Read);
		}

		public static void printf(string Format, params object[] Parameters)
		{
			Console.Write(C.sprintf(Format, Parameters));
		}
	}
}

Hi,

Thanks for the report.

I'll try to look it quickly (this WE if I can).

I'll try to reproduce your issue on .Net and on in original DLL Swiss Ephemeris to see if this error is raised on the original code too.

You are awesome, thanks a lot! I look forward to your findings. Good luck :)

BTW, I am not sure if this is related, but there seems to be other problems when using JPL ephemerides. For example:
swe.swe_sol_eclipse_when_glob(jd, SwissEph.SEFLG_JPLEPH, SwissEph.SE_ECL_TOTAL, tret, false, ref serr);
fails with

"jd 2689359.814575 outside JPL eph. range 2287184.50 .. 2688976.50; \nusing Moshier Eph; "

but
swe.swe_sol_eclipse_when_glob(jd, SwissEph.SEFLG_SWIEPH, SwissEph.SE_ECL_TOTAL, tret, false, ref serr);
works beautifully. My input JD is 2457754.5 (i.e. 1.1.2017)

OK I confirm it's a bug of the SwissEph.Net only.

Apparently the opened file is closed BEFORE used by the calculation. I didn't find where, but now I have some ways to find the bug.

I'll continue my search soon.

OK the version 2.6.0.22 fix the bug.

One thing: in your code, set the OnLoadFile event BEFORE using the swe_set_ephe_path() and swe.swe_set_jpl_file() methods because there load file, so in your sample your must be

using (var swe = new SwissEph())
{
  swe.OnLoadFile += swe_OnLoadFile;
  swe.swe_set_ephe_path(@"X:\Projects\Swiss\jplfiles");
  swe.swe_set_jpl_file("de430.eph");
  ...
}

regards,

Again, you are awesome. I can confirm that this issue is fixed.

Regarding the OnLoadFile. Yes, of course, it should be before setting path etc. What was I thinking! :)