1

わかりました、ここに私が思いついたハックがありますが、実際のコードで使用すると問題が発生します。これは私がやりたいことの実例です

class VirtualParent
{
public:
    virtual void printVal() = 0;
};

class Parent : public VirtualParent
{
public:
    virtual void printVal()
    {
        cout << "Val is: " << val << endl;
    }
    void SetVal(foo * v) { val = v; }
protected:
    foo* val;
};

class Child : public Parent
{
public:
    virtual void printVal()
    {
        cout << "From child, Val is: ";
        val->print();
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
    Parent * p_ptr = new Child;
    foo * val = new foo;
    p_ptr->SetVal(val);
    p_ptr->printVal();

    for(int n = 0;n < 100;n++)
    {
        Parent * new_ptr = nullptr;

        //memcpy ( &new_ptr, &p_ptr, sizeof(Parent) );
        memcpy_s( &new_ptr, sizeof(p_ptr),&p_ptr, sizeof(p_ptr) );

        new_ptr->printVal();
    }

    return 0;
}

この例は、memcpy または memcpy_s を使用する場合に機能します。アイデアは、ユーザー派生クラスを関数に渡すことです。これにより、いくつかのコピーが作成されますが、コンパイル時に派生クラスのタイプがわからないため、それを考えました。私が言ったように、それは完全に機能し、それを使用したいエンジンにコピーしました。メモリの問題がどこからともなく現れており、そのハックに関連しているようです。memcpy_s を使用すると、それらのいくつかが解決されます。これは「良い」ことですか、それとももっと良い方法がありますか?

これが「現実世界」のコードです

_Lua::ScriptedEntity * newScript = EntityBase;//nullptr;
//assert(HeapValidate(GetProcessHeap(),0,nullptr));
//memcpy( &newScript, &EntityBase, sizeof(_Lua::ScriptedEntity) );
memcpy_s(&newScript, sizeof(EntityBase), &EntityBase, sizeof(EntityBase));

//assert(HeapValidate(GetProcessHeap(),0,nullptr));

string luaPath = transforms.next_sibling().next_sibling().first_attribute().as_string();

newScript->CompileFile(luaPath.c_str());

auto callback = [&](_Physics::Trigger* trigger,PxTriggerPair* pairs, PxU32 count) 
                            {
                                newScript->SelectScriptFunction("TriggerCallback");
                                newScript->AddParam(trigger->Id);

                                auto data = (_Physics::RayCastingStats*)pairs->otherShape->userData;

                                newScript->AddParam((PxU8)pairs->flags);
                                newScript->AddParam(data->ID);
                                newScript->AddParam((int)data->Type);

                                newScript->AddParam((int)count);

                                newScript->Go(1);

                                return;
                            };
((_Physics::Trigger*)EnginePTR->iPhysics->GetPhysicObject(StartingTriggerID))->InternalCallback = callback;

そしてクラス

//class derived from LuaScript, implements a set of common use functions for AI scripts and similar. Used in the XLL parser.
    class ScriptedEntity : public LuaScript 
    {
    protected:
        static const int NumberOfFunctions = 11;
        std::array<function<int(LuaVirtualMachine& vm)>,NumberOfFunctions> FunctionsArray;
        int m_iMethodBase;
    public:
        ScriptedEntity(LuaVirtualMachine& vm) : LuaScript (vm)
        {
            InternalEntity = new Entity;

            m_iMethodBase = RegisterFunction("GetEntityPos");
            RegisterFunction("GetPlayerPos");
            RegisterFunction("Move");
            RegisterFunction("GetEntityLife");
            RegisterFunction("IsPlayerVisible");
            RegisterFunction("SetOrientationFromLookAt");
            RegisterFunction("RotateAxisUp");
            RegisterFunction("GetEntityOrientation");
            RegisterFunction("Idle");
            RegisterFunction("TeleportBehindPlayer");
            RegisterFunction("ApplyGravity");

            FunctionsArray[0]  = [this](LuaVirtualMachine& vm){ return this->GetEntityPos(vm); };
            FunctionsArray[1]  = [this](LuaVirtualMachine& vm){ return this->GetPlayerPos(vm); };
            FunctionsArray[2]  = [this](LuaVirtualMachine& vm){ return this->Move(vm); };
            FunctionsArray[3]  = [this](LuaVirtualMachine& vm){ return this->GetEntityLife(vm); };
            FunctionsArray[4]  = [this](LuaVirtualMachine& vm){ return this->IsPlayerVisible(vm); };
            FunctionsArray[5]  = [this](LuaVirtualMachine& vm){ return this->SetOrientationFromLookAt(vm); };
            FunctionsArray[6]  = [this](LuaVirtualMachine& vm){ return this->RotateAxisUp(vm); };
            FunctionsArray[7]  = [this](LuaVirtualMachine& vm){ return this->GetEntityOrientation(vm); };
            FunctionsArray[8]  = [this](LuaVirtualMachine& vm){ return this->Idle(vm); };
            FunctionsArray[9]  = [this](LuaVirtualMachine& vm){ return this->TeleportBehindPlayer(vm); };
            FunctionsArray[10] = [this](LuaVirtualMachine& vm){ return this->ApplyGravity(vm); };

            ViewRayCount = 16;
        }

        virtual int ScriptCalling (LuaVirtualMachine& vm, int iFunctionNumber)
        {
            if(iFunctionNumber - m_iMethodBase > NumberOfFunctions)
                return 0;
            else
                return FunctionsArray[iFunctionNumber - m_iMethodBase](vm);
            // The user might want to add functions to the script, and that's done by overloading this function. That's why it's virtual
        }

        // Functions
        //      Prototypes
        int GetEntityPos(LuaVirtualMachine& vm);
        int GetPlayerPos(LuaVirtualMachine& vm);
        int AttackPlayer(LuaVirtualMachine& vm);
        int Move(LuaVirtualMachine& vm);
        int GetEntityLife(LuaVirtualMachine& vm);
        int GetEntityRawDamage(LuaVirtualMachine& vm);
        int IsPlayerVisible(LuaVirtualMachine& vm);
        int SetOrientationFromLookAt(LuaVirtualMachine& vm);
        int RotateAxisUp(LuaVirtualMachine& vm);
        int GetEntityOrientation(LuaVirtualMachine& vm);
        int Idle(LuaVirtualMachine& vm);
        int TeleportBehindPlayer(LuaVirtualMachine& vm);
        int ApplyGravity(LuaVirtualMachine& vm);
        int ShootPlayer(LuaVirtualMachine& vm);

        //      Defined
        bool Update(float ElapsedTime)
        {
            SelectScriptFunction("Update");
            AddParam(ElapsedTime);

            Go(1);
            SelectScriptFunction("Clear"); // dummy function to clean the stack
            Go();
            return InternalEntity->Alive;
        }

        void HandleReturns (LuaVirtualMachine& vm, const char *strFunc)
        {
            if(string(strFunc) == "Update")
            {
                // frames returns an answer of the stack
                lua_State *state = (lua_State *) vm;
                InternalEntity->Alive = lua_tonumber(state,-1) != 0;
            }
        }

        // Vars
        Entity * InternalEntity;
        void * EnginePTR_voidptr;
        int PhysicID,VisualID,PlayerID;
        int ViewRayCount;
    };

また、memcpy は内部で発生します。

 HRESULT LoadSceneSimple(string Path,
                                        int StartingModelID,
                                        int StartingInstanceID,
                                        int StartingEmmitterID,
                                        int CameraID,
                                        int StartingTriggerID,
                                        int StartingMaterialID,
                                        int StartingPhysicsID,
                                        int ShaderID,
                                        void* engPtr,function<void(_X3D::BaseEffect* effect, _X3D::MaterialValues* matt,int ObjectID,int ShaderID)> MaterialCallback,
                                        string subfolder,
                                        _Lua::ScriptedEntity * EntityBase, string LuaSubfolder);
4

1 に答える 1

7

ポインタをコピーしているだけです。

それでもmemcpy、具象クラスに基づいて異なる可能性がある関連メモリ (ポインターが指している) の大きさを知る必要があるため、しようとしている方法を使用することはできません。

意図したことを行う 1 つの方法は、Parent* Parent::clone()によってオーバーライドされる仮想関数を追加することですChild* Child::clone()

Parent* new_parent = p_ptr->clone()次に、サブクラスを知らなくても、次のようなことができます。

この関数は、正しい/同等のタイプのヒープ メモリclone()の割り当て ( ) を処理すると想定されています。new

于 2013-06-02T07:28:35.873 に答える