ygrenier / SwissEphNet

Swiss Ephemeris for .Net. A Swiss Ephemeris portage for .Net.
Other
77 stars 35 forks source link

NULL deref when using JPL ephemeris #27

Closed barissaydag closed 6 years ago

barissaydag commented 6 years ago

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));
        }
    }
}
ygrenier commented 6 years ago

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.

barissaydag commented 6 years ago

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

barissaydag commented 6 years ago

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)

ygrenier commented 6 years ago

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.

ygrenier commented 6 years ago

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,

barissaydag commented 6 years ago

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! :)