mobius3 / tweeny

A modern C++ tweening library
http://mobius3.github.io/tweeny
MIT License
742 stars 53 forks source link

Crash with illegal instruction #18

Closed Ravbug closed 4 years ago

Ravbug commented 4 years ago

When trying to copy a tweeny::tween via assignment, program crashes with Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)

Code to reproduce:

tweeny::tween<double> anim1;

auto anim2 = tweeny::from(2).to(5).during(100).via(tweeny::easing::linear)

anim1 = anim2;  //crash here

System information: macOS 10.15.7 Xcode 11.7 Using C++ 17

mobius3 commented 4 years ago

I wasn't able to compile that code, it shows me error: no viable overloaded '=', which is to be expected. I'm not sure how you can even compile that one. Maybe you can pass me the flags used to compile the code or even share a small xcode project with the example?

mobius3 commented 4 years ago

On a side note, you can avoid this problem temporarily by using doubles as starting values for anim2 (tweeny::from(2.0).... instead of tweeny::from(2)....). This is really odd though, you shouldn't be able to compile this code.

Ravbug commented 4 years ago

I was trying to create a wrapper class, here is more complete (adjusted) code:

    class Tween {
        tweeny::tween<double> anim;
        typedef std::function<bool(double)> stepfunc;
           public:
        Tween(){};

        Tween(const stepfunc& step, double initialValue = 0){
            anim = tweeny::from(initialValue).onStep(step);
        }

        Tween(const Tween& other){
            anim = other.anim;
        }

        //copy assignment
        Tween& operator=(const Tween& other) {
            if (&other == this) {
                return *this;
            }
            anim = other.anim;   //crash here
        }

        template<typename T>
        void AddKeyframe(double value, double time, const T& interpolation){
            anim.to(value).during(time).via(interpolation);
        }

        void step(double scale){
            anim.step((float)scale * (1.0/60));
        }
    };
Tween t;

//in place of my engine's setup hook
int main(){
    t = Tween([=](double d) -> bool{
        hockeytable->transform()->SetLocalRotation(vector3(0,d*0.01,0));
    }); //crashes on executing this line
    t.AddKeyframe(100, 50, tweeny::easing::linear);
}

I am using CMake, it provided the following arguments:

/Applications/Xcode11.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -x objective-c++ -target x86_64-apple-macos10.15 -fmessage-length=0 -fdiagnostics-show-note-include-stack -fmacro-backtrace-limit=0 -Wno-trigraphs -fpascal-strings -O0 -Wno-missing-field-initializers -Wno-missing-prototypes -Wno-return-type -Wno-implicit-atomic-properties -Wno-objc-interface-ivars -Wno-arc-repeated-use-of-weak -Wno-non-virtual-dtor -Wno-overloaded-virtual -Wno-exit-time-destructors -Wno-missing-braces -Wparentheses -Wswitch -Wno-unused-function -Wno-unused-label -Wno-unused-parameter -Wno-unused-variable -Wunused-value -Wno-empty-body -Wno-uninitialized -Wno-unknown-pragmas -Wno-shadow -Wno-four-char-constants -Wno-conversion -Wno-constant-conversion -Wno-int-conversion -Wno-bool-conversion -Wno-enum-conversion -Wno-float-conversion -Wno-non-literal-null-conversion -Wno-objc-literal-conversion -Wno-shorten-64-to-32 -Wno-newline-eof -Wno-selector -Wno-strict-selector-match -Wno-undeclared-selector -Wno-deprecated-implementations -Wno-c++11-extensions -DCMAKE_INTDIR=\"debug\" -D__STDC_LIMIT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_CONSTANT_MACROS -DOBJC_OLD_DISPATCH_PROTOTYPES=1 -isysroot /Applications/Xcode11.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk -fasm-blocks -fstrict-aliasing -Wprotocol -Wdeprecated-declarations -Winvalid-offsetof -g -Wno-sign-conversion -Wno-infinite-recursion -Wno-move -Wno-comma -Wno-block-capture-autoreleasing -Wno-strict-prototypes -Wno-range-loop-analysis -Wno-semicolon-before-method-body -std=gnu++17 -x objective-c++ -MMD -MT dependencies
mobius3 commented 4 years ago

I see. I'll look into it, thanks for the report!

mobius3 commented 4 years ago

I had to do some changes to make it compile on my machine but after that everything went smoothly:


#include "tweeny.h"

class Tween {
  tweeny::tween<double> anim;
  typedef std::function<bool(double)> stepfunc;
public:
  Tween(){};

  Tween(const stepfunc& step, double initialValue = 0){
    anim = tweeny::from(initialValue).onStep(step);
  }

  Tween(const Tween& other){
    anim = other.anim;
  }

  //copy assignment
  Tween& operator=(const Tween& other) {
    if (&other == this) {
      return *this;
    }
    anim = other.anim;   //crash here
    return *this;
  }

  template<typename T>
  void AddKeyframe(double value, double time, T interpolation){ // was const T & interpolation, that was causing linking errors for me
    anim.to(value).during(time).via(interpolation);
  }

  void step(double scale){
    anim.step((float)(scale * (1.0/60))); // had to cast everything to float
  }
};

Tween t;

int main(int argc, char ** argv) {
  t = Tween([=](double d) -> bool{
    return false; // this was giving me a warning
  });
  t.AddKeyframe(100, 50, tweeny::easing::linear);
  return 0;
}

This is just my initial test on Linux, I'll test it on my MacOS machine as well but so far no crashes. If you run it inside a debugger, does it tell you which line inside tweeny it's crashing? Maybe I can understand the error better.

Ravbug commented 4 years ago

Changing the line in my file to match

  void AddKeyframe(double value, double time, T interpolation){ // was const T & interpolation, that was causing linking errors for me

solved the illegal instruction error for me. I'm still unsure why it compiled on Mac before, but the issue is resolved.

mobius3 commented 4 years ago

That is really odd indeed. Well, I'll close this issue for now, please let me know if there's anything else.