-1

I've defined a class named SkillExecutionOperand, which is an operand being operated on. when I go to convert the class into a derived, the s_skill_execution_operation_config does not get copied and is uninitialized or contains garbage values.

        class SkillExecutionOperand : public CombatOperand
        {
        public:
            struct s_skill_execution_operation_config
            {
                int skill_id{ 0 }, skill_lv{ 0 };
                int16_t pos_x{ 0 }; 
                int16_t pos_y{ 0 };
                std::string contents{ "" };
                std::shared_ptr<const skill_config_data> skd{nullptr};
                std::shared_ptr<SkillExecution> skill_execution{nullptr};
            };
            SkillExecutionOperand() = delete;
            SkillExecutionOperand(std::shared_ptr<Entity> source, std::shared_ptr<Entity> target, s_skill_execution_operation_config config)
            : CombatOperand(source, target, COMBAT_OPERAND_SKILL_EXECUTION), _config(config) { }
            ~SkillExecutionOperand() { }

            s_skill_execution_operation_config &get_config() { return _config; }

            void operator=(const SkillExecutionOperand &operand)
            {
                _config = operand._config;
            }
        private:
            s_skill_execution_operation_config _config;
        };

Converting the base to derived, the execution stops at the second line of the following statements and throws me a "String too long" error -

[[noreturn]] inline void _Xlen_string() {
    _Xlength_error("string too long");
}

    CombatRegistry::SkillExecutionOperation::SkillExecutionOperand &operand = static_cast<CombatRegistry::SkillExecutionOperation::SkillExecutionOperand&>(get_operand());
    CombatRegistry::SkillExecutionOperation::SkillExecutionOperand::s_skill_execution_operation_config &config = operand.get_config();

enter image description here

Edit - The code for get_operand() is as follows


    class CombatOperation
    {
    public:
        // ...
        CombatOperand get_operand() { return _operand; }
        // ...

    protected:
        CombatOperand _operand;
        // ...
    };
SagunKho
  • 985
  • 10
  • 26
  • 1
    What does `get_operand` look like? Show a [mcve]. I suspect undefined behavior there, perhaps returning a reference to a local variable. Or perhaps the object it returns is not in fact of type `SkillExecutionOperand` – Igor Tandetnik Aug 12 '23 at 04:57
  • Edited the post with the `get_operand()` code – SagunKho Aug 12 '23 at 05:20
  • `CombatOperand _operand` can't contain a derived class, you need to use a pointer. `get_operand` needs to return by reference, not by value – Alan Birtles Aug 12 '23 at 06:25
  • With the definition as shown, the original code shouldn't compile. `get_operand()` returns an lvalue but you are casting it to a non-const lvalue reference. Anyway, as I suspected, `get_operand()` returns an object that's not in fact `SkillExecutionOperand`, so attempts to treat it as one exhibit undefined behavior. – Igor Tandetnik Aug 12 '23 at 14:40

0 Answers0