从 Cocos2d::Layer 派生的 class 有一个指针数据成员。该成员也有向量容器。调用 vector::push_back 时崩溃
A class derived from Cocos2d::Layer has a Pointer Data Member. This member also has vector container. When vector::push_back is called it crashes
我尽最大努力编辑了这篇文章。希望它现在是最小的、完整的和可验证的示例
-
- 我目前的游戏使用的是 Cocos2dx V3.6
- 我描述的问题只发生在 cocos2d::Layer
的自定义派生 classes 中
- cocos2dx 使用静态创建函数来模拟 ObjC 版本的自动释放功能。在此创建函数中调用虚拟 init() 方法和构造函数。它是使用 CREATE_FUNC 宏生成的。
问题如标题所述。我有一个来自 cocos2d::Layer (GameWorldLayer) 的自定义派生 class。它有一个指针数据成员 (m_bar)。 m_bar 也有一个 std:vector 属性 (m_container)。我在 GameWorldLayer 的重写虚拟 init() 中初始化了 m_bar。因此,每当我尝试将某些东西推入 m_container 向量时,我都会得到 EXP_BAD_ACCESS.
如果我在虚拟 init() 方法之外初始化指针数据成员 (m_bar),那么一切正常。
简单来说,我只是不明白为什么在虚拟 init() 方法之外初始化指针数据成员可以工作,但在内部初始化时完全失败。
我尝试简化代码并保持最低限度,如果你尝试使用 IDE(我正在使用 xcode 顺便说一句)你应该得到相同的 EXP_BAD_ACCESS 我保持得到。 (我相信你已经知道了,但你还需要cocos2dx 3.6)
GameWorldLayer.h
#ifndef __Flide__GameWorldLayer__
#define __Flide__GameWorldLayer__
#include "cocos2d.h"
#include "bar.h"
class GameWorldLayer : public cocos2d::Layer
{
private:
Bar * m_bar;
public:
static cocos2d::Scene* createScene();
virtual bool init();
CREATE_FUNC(GameWorldLayer);
void AddSomethingToBar();
~GameWorldLayer();//destructor
};
GameWorldLayer.cpp
#include "GameWorldLayer.h"
GameWorldLayer::~GameWorldLayer()
{
delete m_bar;
}
cocos2d::Scene* GameWorldLayer::createScene()
{
// 'scene' is an autorelease object
auto scene = cocos2d::Scene::create();
// 'layer' is an autorelease object
auto layer = GameWorldLayer::create();
// add layer as a child to scene
scene->addChild(layer);
// return the scene
return scene;
}
bool GameWorldLayer::init()
{
//1. super init first
if ( !Layer::init())
{
return false;
}
m_bar = new Bar();
return true;
}
void GameWorldLayer::AddSomethingToBar()
{
m_bar->PushContainer();
}
Bar.h
#ifndef __Flide__bar__
#define __Flide__bar__
#include <vector>
#include <stdio.h>
using namespace cocos2d;
class Bar
{
private:
std::vector<int> m_container;
public:
Bar(); //constructor
~Bar();//destructor
void PushContainer(); //pushes something into m_container.
};
#endif /* defined(__Flide__bar__) */
Bar.cpp
#include "bar.h"
Bar::Bar()
{
}
Bar::~Bar()
{
m_container.clear();
}
void Bar::PushContainer()
{
m_container.push_back(1);//pushing an integer
}
我认为没有必要,只是为了完整性。我初始化 GameWorldLayer,然后在 AppDelegate::applicationDidFinishLaunching().
中调用 GameWorldLayer::AddSomethingToBar()
bool AppDelegate::applicationDidFinishLaunching()
{
...
// create a scene. it's an autorelease object
auto scene = GameWorldLayer::createScene();
((GameWorldLayer*)scene)->AddSomethingToBar();
...
}
我的钱花在了 GameWorldLayer::init()
上,它并没有像您想象的那样被调用。 m_pBar
将属于您在此处创建的图层:auto layer = GameWorldLayer::create();
,而不属于您返回的 Scene
对象。
因此您的 Scene
对象将无法访问 m_pBar
,因为 m_pBar
不存在于 cocos2d::Scene
中。在这种情况下,铸造也没有任何好处。
此外,这个演员 (((GameWorldLayer*)scene)
) 很糟糕。你至少应该使用 dynamic_cast
我尽最大努力编辑了这篇文章。希望它现在是最小的、完整的和可验证的示例
-
- 我目前的游戏使用的是 Cocos2dx V3.6
- 我描述的问题只发生在 cocos2d::Layer 的自定义派生 classes 中
- cocos2dx 使用静态创建函数来模拟 ObjC 版本的自动释放功能。在此创建函数中调用虚拟 init() 方法和构造函数。它是使用 CREATE_FUNC 宏生成的。
问题如标题所述。我有一个来自 cocos2d::Layer (GameWorldLayer) 的自定义派生 class。它有一个指针数据成员 (m_bar)。 m_bar 也有一个 std:vector 属性 (m_container)。我在 GameWorldLayer 的重写虚拟 init() 中初始化了 m_bar。因此,每当我尝试将某些东西推入 m_container 向量时,我都会得到 EXP_BAD_ACCESS.
如果我在虚拟 init() 方法之外初始化指针数据成员 (m_bar),那么一切正常。
简单来说,我只是不明白为什么在虚拟 init() 方法之外初始化指针数据成员可以工作,但在内部初始化时完全失败。
我尝试简化代码并保持最低限度,如果你尝试使用 IDE(我正在使用 xcode 顺便说一句)你应该得到相同的 EXP_BAD_ACCESS 我保持得到。 (我相信你已经知道了,但你还需要cocos2dx 3.6)
GameWorldLayer.h
#ifndef __Flide__GameWorldLayer__
#define __Flide__GameWorldLayer__
#include "cocos2d.h"
#include "bar.h"
class GameWorldLayer : public cocos2d::Layer
{
private:
Bar * m_bar;
public:
static cocos2d::Scene* createScene();
virtual bool init();
CREATE_FUNC(GameWorldLayer);
void AddSomethingToBar();
~GameWorldLayer();//destructor
};
GameWorldLayer.cpp
#include "GameWorldLayer.h"
GameWorldLayer::~GameWorldLayer()
{
delete m_bar;
}
cocos2d::Scene* GameWorldLayer::createScene()
{
// 'scene' is an autorelease object
auto scene = cocos2d::Scene::create();
// 'layer' is an autorelease object
auto layer = GameWorldLayer::create();
// add layer as a child to scene
scene->addChild(layer);
// return the scene
return scene;
}
bool GameWorldLayer::init()
{
//1. super init first
if ( !Layer::init())
{
return false;
}
m_bar = new Bar();
return true;
}
void GameWorldLayer::AddSomethingToBar()
{
m_bar->PushContainer();
}
Bar.h
#ifndef __Flide__bar__
#define __Flide__bar__
#include <vector>
#include <stdio.h>
using namespace cocos2d;
class Bar
{
private:
std::vector<int> m_container;
public:
Bar(); //constructor
~Bar();//destructor
void PushContainer(); //pushes something into m_container.
};
#endif /* defined(__Flide__bar__) */
Bar.cpp
#include "bar.h"
Bar::Bar()
{
}
Bar::~Bar()
{
m_container.clear();
}
void Bar::PushContainer()
{
m_container.push_back(1);//pushing an integer
}
我认为没有必要,只是为了完整性。我初始化 GameWorldLayer,然后在 AppDelegate::applicationDidFinishLaunching().
中调用 GameWorldLayer::AddSomethingToBar()bool AppDelegate::applicationDidFinishLaunching()
{
...
// create a scene. it's an autorelease object
auto scene = GameWorldLayer::createScene();
((GameWorldLayer*)scene)->AddSomethingToBar();
...
}
我的钱花在了 GameWorldLayer::init()
上,它并没有像您想象的那样被调用。 m_pBar
将属于您在此处创建的图层:auto layer = GameWorldLayer::create();
,而不属于您返回的 Scene
对象。
因此您的 Scene
对象将无法访问 m_pBar
,因为 m_pBar
不存在于 cocos2d::Scene
中。在这种情况下,铸造也没有任何好处。
此外,这个演员 (((GameWorldLayer*)scene)
) 很糟糕。你至少应该使用 dynamic_cast