好的,这是我提出的一些黑客攻击,但我在现实代码中使用它时遇到了一些问题。这是我想要做的一个工作示例
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);
答案 0 :(得分:7)
你只是在复制指针。
即便如此,你也无法按照你想要的方式使用memcpy
,因为你需要知道相关内存的大小(指针指向的内存),这可能因具体类而异。
执行您想要的操作的一种方法是添加虚拟Parent* Parent::clone()
函数,然后由Child* Child::clone()
覆盖。
然后你可以做Parent* new_parent = p_ptr->clone()
之类的事情,而不需要知道子类。
假设clone()
函数将负责为正确/等效类型分配(new
)堆内存。