记录一下今天写的bug = =:析构顺序不正确导致abort()异常 (析构了栈上的变量,这个变量含有生命周期比他长的类的成员变量)
代码如下:
class EntityTestLayer :public BlackPearl::Layer {
public:
EntityTestLayer(const std::string& name, BlackPearl::SystemManager *systemManager, BlackPearl::EntityManager *entityManager)
: Layer(name, systemManager, entityManager)
{
// BlackPearl::Object *m_CameraObj;
BlackPearl::Entity *entity = entityManager->CreateEntity();
BlackPearl::Object CameraObj(entity->GetEntityManager(), entity->GetId());
m_CameraComponent = CameraObj.AddComponent<BlackPearl::PerspectiveCamera>();
m_CameraComponent->SetPosition(glm::vec3(0.0f, 0.0f, 8.0f));
m_CameraPosition = m_CameraComponent->GetPosition();
m_CameraRotation.Yaw = m_CameraComponent->Yaw();
m_CameraRotation.Pitch = m_CameraComponent->Pitch();
glm::vec3 pointLightPositions[] = {
glm::vec3(2.3f, 0.2f, 2.0f),
glm::vec3(2.3f, -3.3f, -4.0f),
glm::vec3(-2.7f, 3.0f, -7.5f),
//glm::vec3(-4.0f, 2.0f, -12.0f),
};
std::vector<BlackPearl::Light::Props> pointLightProps = {
{{0.2f, 0.2f, 0.2f},{ 1.0f, 0.2f, 0.1f},{1.0f, 1.0f, 1.0f}},
{{0.2f, 0.2f, 0.2f},{ 0.2f, 1.0f, 0.1f},{1.0f, 1.0f, 1.0f}},
{{0.2f, 0.2f, 0.2f},{ 0.1f, 0.2f, 1.0f},{1.0f, 1.0f, 1.0f}}
};
for (int i = 0; i < 1; i++)
{
BlackPearl::Entity* lightEntity = entityManager->CreateEntity();
BlackPearl::Object LightObj(lightEntity->GetEntityManager(), lightEntity->GetId());
auto ptr = LightObj.AddComponent<BlackPearl::PointLight>();
m_LightComponent.reset(ptr);
m_LightComponent->SetProps(pointLightProps[0]);
std::dynamic_pointer_cast<BlackPearl::PointLight>(m_LightComponent)->SetPosition(pointLightPositions[0]);
std::dynamic_pointer_cast<BlackPearl::PointLight>(m_LightComponent)->SetAttenuation(BlackPearl::PointLight::Attenuation(3250));
m_LightSources.AddLight(m_LightComponent);
}
BlackPearl::Renderer::Init();
std::cout << "_______________________" << std::endl;
/*systemManager->Add<InputSystem>();
systemManager->Add<RenderSystem>();
systemManager->Configure();*/
}
//。。。。。。
private:
BlackPearl::LightSources m_LightSources;
std::shared_ptr<BlackPearl::Light> m_LightComponent;
BlackPearl::Camera* m_CameraComponent;
glm::vec3 m_CameraPosition = { 0.0f,0.0f,0.0f };
struct CameraRotation {
float Yaw;
float Pitch;
};
CameraRotation m_CameraRotation;
float m_LastMouseX;
float m_LastMouseY;
float m_CameraMoveSpeed = 5.0f;
float m_CameraRotateSpeed = 9.0f;
};
当退出for循环时触发异常:
AddComponent函数把 m_LightComponent添加到LightObj
template<typename C, typename ...Args>
C* AddComponent(Args ...args)
{
//GE_ASSERT(Valid(), "invalid entity" + std::to_string(m_Id.index())); //TODO::https://bbs.csdn.net/topics/391862079
//C* component = m_EntityManager->AddComponent(m_Id, args);
const BaseComponent::Family family = GetComponentFamliy<C>();
//Returns whether the bit at family pos is set (i.e., whether it is one).
GE_ASSERT(!m_ComponentMask.test(family), "Component already existed!")
m_ComponentMask.set(family);
//所有的component都用Create实例化-->方便子类继承!
//C* component = C::Create(m_EntityManager, m_Id, std::forward<Args>(args)...);
C* component = DBG_NEW C(m_EntityManager, m_Id, std::forward<Args>(args)...);
m_Components.insert(std::make_pair(C::Famliy(), component));
return component;
}
异常的原因是:LightObj是一个栈上分配的变量,LightObj所含有的 m_LightComponet 是EntityTestLayer 这个类的成员变量,
当退出for循环是 LightObj会被析构!
virtual ~Object() {
Destroy();
};
void Object::Destroy()
{
for (auto& pair : m_Components) { //TODO::看一下要不要用智能指针
BaseComponent* component = pair.second;
delete component;
component = nullptr;
}
m_ComponentMask.reset();
m_EntityManager->DestroyEntity(m_Id);
m_Components.clear();
}
它所含有的 components都会被delete掉,而 m_LightComponent由于是成员变量,它的生命周期是随着类的销毁而销毁的!而退出for循环时类EntityTestLayer 依旧存在,所以在析构栈上的LightObj时就会发生异常!!同理CameraObj也一样!
修复后的代码:
class EntityTestLayer :public BlackPearl::Layer {
public:
EntityTestLayer(const std::string& name, BlackPearl::SystemManager *systemManager, BlackPearl::EntityManager *entityManager)
: Layer(name, systemManager, entityManager)
{
// BlackPearl::Object *m_CameraObj;
BlackPearl::Entity *entity = entityManager->CreateEntity();
m_CameraObj = new BlackPearl::Object(entity->GetEntityManager(), entity->GetId());
m_CameraComponent = m_CameraObj->AddComponent<BlackPearl::PerspectiveCamera>();
//m_CameraComponent = CameraObj.AddComponent<BlackPearl::PerspectiveCamera>();
m_CameraComponent->SetPosition(glm::vec3(0.0f, 0.0f, 8.0f));
m_CameraPosition = m_CameraComponent->GetPosition();
m_CameraRotation.Yaw = m_CameraComponent->Yaw();
m_CameraRotation.Pitch = m_CameraComponent->Pitch();
glm::vec3 pointLightPositions[] = {
glm::vec3(2.3f, 0.2f, 2.0f),
glm::vec3(2.3f, -3.3f, -4.0f),
glm::vec3(-2.7f, 3.0f, -7.5f),
//glm::vec3(-4.0f, 2.0f, -12.0f),
};
std::vector<BlackPearl::Light::Props> pointLightProps = {
{{0.2f, 0.2f, 0.2f},{ 1.0f, 0.2f, 0.1f},{1.0f, 1.0f, 1.0f}},
{{0.2f, 0.2f, 0.2f},{ 0.2f, 1.0f, 0.1f},{1.0f, 1.0f, 1.0f}},
{{0.2f, 0.2f, 0.2f},{ 0.1f, 0.2f, 1.0f},{1.0f, 1.0f, 1.0f}}
};
for (int i = 0; i < 1; i++)
{
BlackPearl::Entity* lightEntity = entityManager->CreateEntity();
m_LightObj = new BlackPearl::Object(lightEntity->GetEntityManager(), lightEntity->GetId());
auto ptr = m_LightObj->AddComponent<BlackPearl::PointLight>();
m_LightComponent.reset(ptr);
m_LightComponent->SetProps(pointLightProps[0]);
std::dynamic_pointer_cast<BlackPearl::PointLight>(m_LightComponent)->SetPosition(pointLightPositions[0]);
std::dynamic_pointer_cast<BlackPearl::PointLight>(m_LightComponent)->SetAttenuation(BlackPearl::PointLight::Attenuation(3250));
m_LightSources.AddLight(m_LightComponent);
}
BlackPearl::Renderer::Init();
std::cout << "_______________________" << std::endl;
/*systemManager->Add<InputSystem>();
systemManager->Add<RenderSystem>();
systemManager->Configure();*/
}
void OnUpdate(BlackPearl::Timestep ts) override {
//m_SystemManager->Update<InputSystem>(ts);
//m_SystemManager->Update<RenderSystem>(ts);
InputCheck(ts);
// render
BlackPearl::RenderCommand::SetClearColor({ 0.0f,0.0f,0.0f,0.0f });
//m_Shader->Bind();
BlackPearl::Renderer::BeginScene(*m_CameraComponent, m_LightSources);
}
void OnImguiRender() override {
ImGui::Begin("Settings");
ImGui::Text("Hello World");
ImGui::End();
}
void OnAttach() override {
}
void InputCheck(float ts)
{
if (BlackPearl::Input::IsKeyPressed(BP_KEY_W)) {
m_CameraPosition += m_CameraComponent->Front() * m_CameraMoveSpeed * ts;
}
else if (BlackPearl::Input::IsKeyPressed(BP_KEY_S)) {
m_CameraPosition -= m_CameraComponent->Front()* m_CameraMoveSpeed * ts;
}
if (BlackPearl::Input::IsKeyPressed(BP_KEY_A)) {
m_CameraPosition -= m_CameraComponent->Right() * m_CameraMoveSpeed * ts;
}
else if (BlackPearl::Input::IsKeyPressed(BP_KEY_D)) {
m_CameraPosition += m_CameraComponent->Right() * m_CameraMoveSpeed * ts;
}
if (BlackPearl::Input::IsKeyPressed(BP_KEY_E)) {
m_CameraPosition -= m_CameraComponent->Up() * m_CameraMoveSpeed * ts;
}
else if (BlackPearl::Input::IsKeyPressed(BP_KEY_Q)) {
m_CameraPosition += m_CameraComponent->Up() * m_CameraMoveSpeed * ts;
}
// ---------------------Rotation--------------------------------------
float posx = BlackPearl::Input::GetMouseX();
float posy = BlackPearl::Input::GetMouseY();
if (BlackPearl::Input::IsMouseButtonPressed(BP_MOUSE_BUTTON_RIGHT)) {
if (BlackPearl::Input::IsFirstMouse()) {
BlackPearl::Input::SetFirstMouse(false);
m_LastMouseX = posx;
m_LastMouseY = posy;
}
float diffx = posx - m_LastMouseX;
float diffy = -posy + m_LastMouseY;
m_LastMouseX = posx;
m_LastMouseY = posy;
m_CameraRotation.Yaw += diffx * m_CameraRotateSpeed * ts;
m_CameraRotation.Pitch += diffy * m_CameraRotateSpeed * ts;
if (m_CameraRotation.Pitch > 89.0f)
m_CameraRotation.Pitch = 89.0f;
if (m_CameraRotation.Pitch < -89.0f)
m_CameraRotation.Pitch = -89.0f;
m_CameraComponent->SetRotation(m_CameraRotation.Yaw, m_CameraRotation.Pitch);
}
else {
m_LastMouseX = posx;//lastMouse时刻记录当前坐标位置,防止再次点击右键时,发生抖动!
m_LastMouseY = posy;
}
m_CameraComponent->SetPosition(m_CameraPosition);
}
private:
BlackPearl::LightSources m_LightSources;
BlackPearl::Object *m_LightObj;
BlackPearl::Object *m_CameraObj;
std::shared_ptr<BlackPearl::Light> m_LightComponent;
BlackPearl::Camera* m_CameraComponent;
glm::vec3 m_CameraPosition = { 0.0f,0.0f,0.0f };
struct CameraRotation {
float Yaw;
float Pitch;
};
CameraRotation m_CameraRotation;
float m_LastMouseX;
float m_LastMouseY;
float m_CameraMoveSpeed = 5.0f;
float m_CameraRotateSpeed = 9.0f;
};
成功跑通: