Destroying ChaiScript object from within ChaiScript


#1

I have a ChaiScript instance allocated on the heap which I would like to destroy from within ChaiScript. Here is an example of what I would like to do:

#include <chaiscript/chaiscript.hpp>

chaiscript::ChaiScript *chai = new chaiscript::ChaiScript();

void deleteChai() {
    delete chai;
}

main() {
    chai->add(chaiscript::fun(&deleteChai), "deleteChai");
    chai->eval("deleteChai()");
}

This fails with the error:

/ChaiScript_Extras/include/chaiscript/dispatchkit/dispatchkit.hpp:965: void chaiscript::detail::Dispatch_Engine::pop_function_call(): Assertion `s.call_depth >= 0’ failed.

What is the best way of accomplishing this?


#2

You’re attempting to delete the ChaiScript engine while using it. I cannot think of a way to do this that would make sense. It would be kind of equivalent to doing something like:

class MyClass {
  std::string someString;
  void deleteMe() {
    delete this;
    std::cout << someString; // what happens here? You've just deleted someString
  };
};

I don’t know what the end goal is, but if you just want something that’s heap allocated and can clean itself up when it’s no longer in use:

#include <chaiscript/chaiscript.hpp>

std::unique_ptr<chaiscript::ChaiScript> chai(new chaiscript::ChaiScript());

main() {
    chai->add(chaiscript::fun(&deleteChai), "deleteChai");
    // chai will be automatically deleted and cleaned up by the compiler after main exits
}

#3

I know that it seems a bit unintuitive. The inspiration comes from a ChaiScript instance being part of a game object allocated on the heap that wants to delete itself from within the script. The solution I was imagining was kind of like the following:

void deleteChai() {
    chai->stop_running(); // stops ChaiScript evaluation at its current location
    delete chai; // this will now work since ChaiScript has stopped evaluating
}

#4

I think this is the concept you want. I’d still recommend using unique_ptr in case the deleteChai function is never called. Then you would do chai.reset() instead of delete chai. It would not increase overhead or anything, just reduce the chance of having a memory leak.

#include <chaiscript/chaiscript.hpp>

chaiscript::ChaiScript *chai = new chaiscript::ChaiScript();
bool delayed_delete = false;

void deleteChai() {
  delayed_delete = true;
}

main() {
    chai->add(chaiscript::fun(&deleteChai), "deleteChai");
    chai->eval("deleteChai()");
    if (delayed_delete) { 
        delete chai;
        chai = nullptr;
    }
}

#5

I will use this. Thanks for your help.