わかりました、ここに私が思いついたハックがありますが、実際のコードで使用すると問題が発生します。これは私がやりたいことの実例です
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);