Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. Other Discussions
  3. Clever Code
  4. Error calling VB6 DLL [modified*2]

Error calling VB6 DLL [modified*2]

Scheduled Pinned Locked Moved Clever Code
helpcomdebuggingquestion
16 Posts 7 Posters 3 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • S Offline
    S Offline
    Shog9 0
    wrote on last edited by
    #1

    Here's the (very much simplified) code that brought a smile to my face today:

    void DoTheChecking(double diameter, double rate)
    {
       // WheelLib is a pointer to a COM object implemented in VB6
       HRESULT hr = WheelLib->CheckWheel(diameter, rate);
       if (!SUCCEEDED(hr))
          FreakOut();
    }

    'Thing is, this wonderful little routine has been in use for years without problems. Last week, we started calling it from a new program, and all hell broke loose. The CheckWheel() call failed every time. I figured there had to be something different in how it was being called, so i dropped in a breakpoint and checked the parameters. But, they looked just fine. In fact, the other callers were passing the exact same values and working perfectly. So then i took a look at the new caller:

    ...
    double diameter = 54.5;
    double rate = 15000.0;
       double factor = 54.012;
       double cutoff = factor/scale;
       // TODO: do something useful with cutoff

    DoTheChecking(diameter, rate);
    ...

    Ah. That's it. ;) Hint #1: scale has the value 0.0 Solution: The FP code that VB generates checks the FP status word periodically, and throws an exception if it indicates an error. It does not, however, clear the status word upon being called from an external source. The div-by-zero bug in the calling code, even though it didn't cause any problems directly, left the _SW_ZERODIVIDE bit set in the status word, and VB picked it up and ran with it. Tucking in a call to _clearfp() in DoTheChecking() took care of things (as did building the VB DLL with FP error-checking disabled).


    Last modified: 10hrs 55mins after originally posted -- Added solution

    But who is the king of all of these folks?

    L B D P C 5 Replies Last reply
    0
    • S Shog9 0

      Here's the (very much simplified) code that brought a smile to my face today:

      void DoTheChecking(double diameter, double rate)
      {
         // WheelLib is a pointer to a COM object implemented in VB6
         HRESULT hr = WheelLib->CheckWheel(diameter, rate);
         if (!SUCCEEDED(hr))
            FreakOut();
      }

      'Thing is, this wonderful little routine has been in use for years without problems. Last week, we started calling it from a new program, and all hell broke loose. The CheckWheel() call failed every time. I figured there had to be something different in how it was being called, so i dropped in a breakpoint and checked the parameters. But, they looked just fine. In fact, the other callers were passing the exact same values and working perfectly. So then i took a look at the new caller:

      ...
      double diameter = 54.5;
      double rate = 15000.0;
         double factor = 54.012;
         double cutoff = factor/scale;
         // TODO: do something useful with cutoff

      DoTheChecking(diameter, rate);
      ...

      Ah. That's it. ;) Hint #1: scale has the value 0.0 Solution: The FP code that VB generates checks the FP status word periodically, and throws an exception if it indicates an error. It does not, however, clear the status word upon being called from an external source. The div-by-zero bug in the calling code, even though it didn't cause any problems directly, left the _SW_ZERODIVIDE bit set in the status word, and VB picked it up and ran with it. Tucking in a call to _clearfp() in DoTheChecking() took care of things (as did building the VB DLL with FP error-checking disabled).


      Last modified: 10hrs 55mins after originally posted -- Added solution

      But who is the king of all of these folks?

      L Offline
      L Offline
      leppie
      wrote on last edited by
      #2

      I dont get it :sigh: Is it an instance method maybe?

      xacc.ide - now with IronScheme support
      IronScheme - 1.0 alpha 1 out now

      S 1 Reply Last reply
      0
      • S Shog9 0

        Here's the (very much simplified) code that brought a smile to my face today:

        void DoTheChecking(double diameter, double rate)
        {
           // WheelLib is a pointer to a COM object implemented in VB6
           HRESULT hr = WheelLib->CheckWheel(diameter, rate);
           if (!SUCCEEDED(hr))
              FreakOut();
        }

        'Thing is, this wonderful little routine has been in use for years without problems. Last week, we started calling it from a new program, and all hell broke loose. The CheckWheel() call failed every time. I figured there had to be something different in how it was being called, so i dropped in a breakpoint and checked the parameters. But, they looked just fine. In fact, the other callers were passing the exact same values and working perfectly. So then i took a look at the new caller:

        ...
        double diameter = 54.5;
        double rate = 15000.0;
           double factor = 54.012;
           double cutoff = factor/scale;
           // TODO: do something useful with cutoff

        DoTheChecking(diameter, rate);
        ...

        Ah. That's it. ;) Hint #1: scale has the value 0.0 Solution: The FP code that VB generates checks the FP status word periodically, and throws an exception if it indicates an error. It does not, however, clear the status word upon being called from an external source. The div-by-zero bug in the calling code, even though it didn't cause any problems directly, left the _SW_ZERODIVIDE bit set in the status word, and VB picked it up and ran with it. Tucking in a call to _clearfp() in DoTheChecking() took care of things (as did building the VB DLL with FP error-checking disabled).


        Last modified: 10hrs 55mins after originally posted -- Added solution

        But who is the king of all of these folks?

        B Offline
        B Offline
        Baconbutty
        wrote on last edited by
        #3

        What is?

        I still remember having to write your own code in FORTRAN rather than be a cut and paste merchant being pampered by colour coded Intellisense - ahh proper programming - those were the days :)

        1 Reply Last reply
        0
        • S Shog9 0

          Here's the (very much simplified) code that brought a smile to my face today:

          void DoTheChecking(double diameter, double rate)
          {
             // WheelLib is a pointer to a COM object implemented in VB6
             HRESULT hr = WheelLib->CheckWheel(diameter, rate);
             if (!SUCCEEDED(hr))
                FreakOut();
          }

          'Thing is, this wonderful little routine has been in use for years without problems. Last week, we started calling it from a new program, and all hell broke loose. The CheckWheel() call failed every time. I figured there had to be something different in how it was being called, so i dropped in a breakpoint and checked the parameters. But, they looked just fine. In fact, the other callers were passing the exact same values and working perfectly. So then i took a look at the new caller:

          ...
          double diameter = 54.5;
          double rate = 15000.0;
             double factor = 54.012;
             double cutoff = factor/scale;
             // TODO: do something useful with cutoff

          DoTheChecking(diameter, rate);
          ...

          Ah. That's it. ;) Hint #1: scale has the value 0.0 Solution: The FP code that VB generates checks the FP status word periodically, and throws an exception if it indicates an error. It does not, however, clear the status word upon being called from an external source. The div-by-zero bug in the calling code, even though it didn't cause any problems directly, left the _SW_ZERODIVIDE bit set in the status word, and VB picked it up and ran with it. Tucking in a call to _clearfp() in DoTheChecking() took care of things (as did building the VB DLL with FP error-checking disabled).


          Last modified: 10hrs 55mins after originally posted -- Added solution

          But who is the king of all of these folks?

          D Offline
          D Offline
          Dewm Solo
          wrote on last edited by
          #4

          I fail to see it as well. Except for rate maybe being a too big value? The rest looks fine from where I stand (or sit I should say).

          Dewm Solo - Managed C++ Developer

          1 Reply Last reply
          0
          • L leppie

            I dont get it :sigh: Is it an instance method maybe?

            xacc.ide - now with IronScheme support
            IronScheme - 1.0 alpha 1 out now

            S Offline
            S Offline
            Shog9 0
            wrote on last edited by
            #5

            Nope. There's a reason it took me the better part of the afternoon to figure it out... it is subtle. I've added a pretty good hint now though, one which i had to dig through three files, four classes, and around six methods to actually find originally. ;)

            1 Reply Last reply
            0
            • S Shog9 0

              Here's the (very much simplified) code that brought a smile to my face today:

              void DoTheChecking(double diameter, double rate)
              {
                 // WheelLib is a pointer to a COM object implemented in VB6
                 HRESULT hr = WheelLib->CheckWheel(diameter, rate);
                 if (!SUCCEEDED(hr))
                    FreakOut();
              }

              'Thing is, this wonderful little routine has been in use for years without problems. Last week, we started calling it from a new program, and all hell broke loose. The CheckWheel() call failed every time. I figured there had to be something different in how it was being called, so i dropped in a breakpoint and checked the parameters. But, they looked just fine. In fact, the other callers were passing the exact same values and working perfectly. So then i took a look at the new caller:

              ...
              double diameter = 54.5;
              double rate = 15000.0;
                 double factor = 54.012;
                 double cutoff = factor/scale;
                 // TODO: do something useful with cutoff

              DoTheChecking(diameter, rate);
              ...

              Ah. That's it. ;) Hint #1: scale has the value 0.0 Solution: The FP code that VB generates checks the FP status word periodically, and throws an exception if it indicates an error. It does not, however, clear the status word upon being called from an external source. The div-by-zero bug in the calling code, even though it didn't cause any problems directly, left the _SW_ZERODIVIDE bit set in the status word, and VB picked it up and ran with it. Tucking in a call to _clearfp() in DoTheChecking() took care of things (as did building the VB DLL with FP error-checking disabled).


              Last modified: 10hrs 55mins after originally posted -- Added solution

              But who is the king of all of these folks?

              P Offline
              P Offline
              PIEBALDconsult
              wrote on last edited by
              #6

              Shog9 wrote:

              Hint: scale has the value 0.0

              Soooo... the post's subject isn't operative?

              S 1 Reply Last reply
              0
              • P PIEBALDconsult

                Shog9 wrote:

                Hint: scale has the value 0.0

                Soooo... the post's subject isn't operative?

                S Offline
                S Offline
                Shog9 0
                wrote on last edited by
                #7

                FP exceptions are masked (as is the default in VC++), and cutoff is never used... ;)

                P B 2 Replies Last reply
                0
                • S Shog9 0

                  Here's the (very much simplified) code that brought a smile to my face today:

                  void DoTheChecking(double diameter, double rate)
                  {
                     // WheelLib is a pointer to a COM object implemented in VB6
                     HRESULT hr = WheelLib->CheckWheel(diameter, rate);
                     if (!SUCCEEDED(hr))
                        FreakOut();
                  }

                  'Thing is, this wonderful little routine has been in use for years without problems. Last week, we started calling it from a new program, and all hell broke loose. The CheckWheel() call failed every time. I figured there had to be something different in how it was being called, so i dropped in a breakpoint and checked the parameters. But, they looked just fine. In fact, the other callers were passing the exact same values and working perfectly. So then i took a look at the new caller:

                  ...
                  double diameter = 54.5;
                  double rate = 15000.0;
                     double factor = 54.012;
                     double cutoff = factor/scale;
                     // TODO: do something useful with cutoff

                  DoTheChecking(diameter, rate);
                  ...

                  Ah. That's it. ;) Hint #1: scale has the value 0.0 Solution: The FP code that VB generates checks the FP status word periodically, and throws an exception if it indicates an error. It does not, however, clear the status word upon being called from an external source. The div-by-zero bug in the calling code, even though it didn't cause any problems directly, left the _SW_ZERODIVIDE bit set in the status word, and VB picked it up and ran with it. Tucking in a call to _clearfp() in DoTheChecking() took care of things (as did building the VB DLL with FP error-checking disabled).


                  Last modified: 10hrs 55mins after originally posted -- Added solution

                  But who is the king of all of these folks?

                  C Offline
                  C Offline
                  CPallini
                  wrote on last edited by
                  #8

                  Do you mean the VB6 code catches the divide exception? unbelievable! :)

                  If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler. -- Alfonso the Wise, 13th Century King of Castile.
                  This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong. -- Iain Clarke

                  S 1 Reply Last reply
                  0
                  • C CPallini

                    Do you mean the VB6 code catches the divide exception? unbelievable! :)

                    If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler. -- Alfonso the Wise, 13th Century King of Castile.
                    This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong. -- Iain Clarke

                    S Offline
                    S Offline
                    Shog9 0
                    wrote on last edited by
                    #9

                    Yup... :)

                    1 Reply Last reply
                    0
                    • S Shog9 0

                      FP exceptions are masked (as is the default in VC++), and cutoff is never used... ;)

                      P Offline
                      P Offline
                      PIEBALDconsult
                      wrote on last edited by
                      #10

                      What's FP?

                      S 1 Reply Last reply
                      0
                      • P PIEBALDconsult

                        What's FP?

                        S Offline
                        S Offline
                        Shog9 0
                        wrote on last edited by
                        #11

                        Floating-point.

                        But who is the king of all of these folks?

                        1 Reply Last reply
                        0
                        • S Shog9 0

                          FP exceptions are masked (as is the default in VC++), and cutoff is never used... ;)

                          B Offline
                          B Offline
                          Brady Kelly
                          wrote on last edited by
                          #12

                          What would something happen if cutoff was used? Would that trigger the previously masked error flag?

                          S 1 Reply Last reply
                          0
                          • B Brady Kelly

                            What would something happen if cutoff was used? Would that trigger the previously masked error flag?

                            S Offline
                            S Offline
                            Shog9 0
                            wrote on last edited by
                            #13

                            cutoff, as calculated in the problem scenario, is NaN. Since exceptions are masked on the C++ side of things, that value will just propagate through any other calculations it's used in. If i were to pass it into VB after clearing the status word, i suspect it would result in an exception being thrown the first time it was used in a calculation, but i haven't actually tried this. Generally, passing NaN around isn't a particularly useful thing to do anyway; the cutoff calculation would have been a rather unpleasant bug on its own if it had actually been used anywhere.

                            But who is the king of all of these folks?

                            B 1 Reply Last reply
                            0
                            • S Shog9 0

                              cutoff, as calculated in the problem scenario, is NaN. Since exceptions are masked on the C++ side of things, that value will just propagate through any other calculations it's used in. If i were to pass it into VB after clearing the status word, i suspect it would result in an exception being thrown the first time it was used in a calculation, but i haven't actually tried this. Generally, passing NaN around isn't a particularly useful thing to do anyway; the cutoff calculation would have been a rather unpleasant bug on its own if it had actually been used anywhere.

                              But who is the king of all of these folks?

                              B Offline
                              B Offline
                              Brady Kelly
                              wrote on last edited by
                              #14

                              That's why I like C#. Division by zero is clearly an exception, and cutoff retains it's initial, or prior value. The above is just plain scary. :~

                              S 1 Reply Last reply
                              0
                              • B Brady Kelly

                                That's why I like C#. Division by zero is clearly an exception, and cutoff retains it's initial, or prior value. The above is just plain scary. :~

                                S Offline
                                S Offline
                                Shog9 0
                                wrote on last edited by
                                #15

                                Brady Kelly wrote:

                                Division by zero is clearly an exception, and cutoff retains it's initial, or prior value.

                                If the exception stops the program, or is otherwise caught outside of the scope in which cutoff is relevant, then that's fine (assuming that the program stopping is not itself somehow catastrophic). But, if the program lives, cutoff now has a potentially-undetectably invalid value. There are trade-offs both ways. Of course, i wouldn't write an exception handler to catch division by zero. I'd either check the divisor first, or the quotient afterwards. Exception handling code is both too awkward to write and too heavy to run for tasks such as these. (BTW - if you were to implement the bit of code i wrote in C#, you wouldn't get an exception either. DivideByZeroException is thrown only by integer division, same as in native code. There's just no option to represent infinity in the integer datatypes.)

                                But who is the king of all of these folks?

                                B 1 Reply Last reply
                                0
                                • S Shog9 0

                                  Brady Kelly wrote:

                                  Division by zero is clearly an exception, and cutoff retains it's initial, or prior value.

                                  If the exception stops the program, or is otherwise caught outside of the scope in which cutoff is relevant, then that's fine (assuming that the program stopping is not itself somehow catastrophic). But, if the program lives, cutoff now has a potentially-undetectably invalid value. There are trade-offs both ways. Of course, i wouldn't write an exception handler to catch division by zero. I'd either check the divisor first, or the quotient afterwards. Exception handling code is both too awkward to write and too heavy to run for tasks such as these. (BTW - if you were to implement the bit of code i wrote in C#, you wouldn't get an exception either. DivideByZeroException is thrown only by integer division, same as in native code. There's just no option to represent infinity in the integer datatypes.)

                                  But who is the king of all of these folks?

                                  B Offline
                                  B Offline
                                  Brady Kelly
                                  wrote on last edited by
                                  #16

                                  But wait, there's more! Casting Infinity to an int gives -2147483648. I can see some nasties happening down that little travelled path.

                                  1 Reply Last reply
                                  0
                                  Reply
                                  • Reply as topic
                                  Log in to reply
                                  • Oldest to Newest
                                  • Newest to Oldest
                                  • Most Votes


                                  • Login

                                  • Don't have an account? Register

                                  • Login or register to search.
                                  • First post
                                    Last post
                                  0
                                  • Categories
                                  • Recent
                                  • Tags
                                  • Popular
                                  • World
                                  • Users
                                  • Groups