Access violation reading location 0x0000001C

Hello everyone, I writing after encountering an error that I can not solve. in a few words I have a problems to create a object (created by me) in a HelloWorldScene function. I immediately place the code that causes the error.

header file

Palla.h

#ifndef PALLA2_H
#define PALLA2_H

#include <cocos2d.h>

class Palla : public cocos2d::Sprite
{
public:
Palla();
private:
cocos2d::RepeatForever* Rotola();
};

#endif // PALLA2_H

cpp file Palla.cpp

#include “Palla.h”

USING_NS_CC;

Palla::Palla()
{
Sprite* palla = Sprite::create(“Palla.png”);
palla->runAction(Rotola());
}

RepeatForever* Palla::Rotola()
{
RotateBy* rotazione = RotateBy::create(0.8, 360);
RepeatForever* AzioneInfinita = RepeatForever::create(rotazione);
return AzioneInfinita;
}

HelloWorldScene.h

#ifndef HELLOWORLD_SCENE_H
#define HELLOWORLD_SCENE_H

#include “cocos2d.h”
#include “Palla.h”

class HelloWorld : public cocos2d::Layer
{
public:
// there’s no ‘id’ in cpp, so we recommend returning the class instance pointer
static cocos2d::Scene* createScene();

// Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
virtual bool init();  

// a selector callback
void menuCloseCallback(cocos2d::Ref* pSender);

// implement the "static create()" method manually
CREATE_FUNC(HelloWorld);

void aggiungiPalla();
cocos2d::Size winSize;
cocos2d::Point origin;

private:
Palla* palla;
};

#endif // HELLOWORLD_SCENE_H


HelloWorldScene.cpp

#include “HelloWorldScene.h”
#include “Palla.h”

USING_NS_CC;

Scene* HelloWorld::createScene()
{
// ‘scene’ is an autorelease object
auto scene = Scene::create();

// 'layer' is an autorelease object
auto layer = HelloWorld::create();

// add layer as a child to scene
scene->addChild(layer);

// return the scene
return scene;

}

// on “init” you need to initialize your instance
bool HelloWorld::init()
{
//////////////////////////////
// 1. super init first
if ( !Layer::init() )
{
return false;
}

winSize = Director::getInstance()->getVisibleSize();
origin = Director::getInstance()->getVisibleOrigin();

aggiungiPalla();
return true;

}

void HelloWorld::aggiungiPalla()
{
palla = new Palla();
if (!palla){ delete palla; }
palla->Node::setPosition((winSize.width / 2) + origin.x, (winSize.height / 2) + origin.y);
this->addChild(palla);
}

void HelloWorld::menuCloseCallback(Ref* pSender)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
MessageBox(“You pressed the close button. Windows Store Apps do not implement a close button.”,“Alert”);
return;
#endif

Director::getInstance()->end();

#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
exit(0);
#endif
}

the error is this
An unhandled exception in 0x0100CE91 in test.exe: 0xC0000005: Access violation reading location 0x0000001C.

in this function

GLuint Texture2D::getName() const
{
return _name;
}

I also tried to change the initialization of 'image in the constructor of my object. with

initWithSpriteFrameName

or

Image* palla = NULL;
palla->initWithImageFile(“Palla.png”);
Texture2D* pallaTexture = NULL;
pallaTexture->initWithImage(palla);
initWithTexture(pallaTexture);

but the error is the same…

thanks in advance for the help.

P.S:i use the compiler VISUAL STUDIO 2013.

after 2 days, and after having been disturbed (sorry), I managed to solve the problem now.
i call the function

initWithFile(“Palla.png”);

can i know how the other functions do not work?

initWithSpriteFrameName
initWithTexture ecc ?

initWith functions aren’t really the promoted style of creating an object, especially if you have access to the overloaded create and createWith functions (they internally call init and setup autorelease, for example).

I’ve had success with using create().
Also just to be safe, I’d initialize your palla pointer (like all pointers).

And not to pick apart your code too much, but this code is unsafe.

if (!palla){ delete palla; }

// In the case that palla is deleted/undefined/null, calling its methods isnt a good idea!
palla->Node::setPosition((winSize.width / 2) + origin.x, (winSize.height / 2) + origin.y);
this->addChild(palla);

I’d recommend instead

if (!palla)
{ 
// Or maybe assert... up to you.
log("Something went wrong!");
 return;
}

// Now we know the pointer is at least non-null.
palla->Node::setPosition((winSize.width / 2) + origin.x, (winSize.height / 2) + origin.y);
this->addChild(palla);

When you create a sprite in Palla’s constructor, no actions can be run because it’s not added to anything active in the scene:

Palla::Palla()
{ 
Sprite* palla = Sprite::create("Palla.png");
// palla sprite not added to node, no actions can be ran.
palla->runAction(Rotola());
// Sprite pointer dies, since autorelease does its job.
}

And as a result your pointer to palla in your scene, is actually a pointer to an uninitialized Sprite node (itself containing a pointer to a temporary node; it dies outside the constructor scope). It won’t get a chance to do anything! I’d take a moment to read up on memory management if you’re not familiar. Also it doesn’t hurt to know how the Scene Graph works (link for more detail).

The “cocos2d-x way” is to use CREATE_FUNC. Since your Palla class is so simple, I recommend avoiding subclassing. But if we did, It’d look something like this (taking into account all of the above tips):

Palla.h

class Palla : public cocos2d::Sprite
{
public:
  CREATE_FUNC(Palla);
// A common pattern is to use init to run setup cocos-related setup code, not in the constructor.
  virtual bool init() override;

  Palla();
  virtual ~Palla();

private:
  cocos2d::RepeatForever* const Rotola();
};

Palla.cpp

Palla::Palla(){}
Palla::~Palla(){}

bool Palla::init()
{
  if (!Sprite::create()) {return false;}
// This logic is called whenever an instance is created. 
// Most of the time, you want to do cocos related things here, NOT in the constructor (the constructor is called before the node is finished initializing, AFAIK).
  Sprite* palla = Sprite::create("Palla.png");
// Run your actions if the sprite was created.
  if (palla)
  {
// Actions will only be ran if the node is connected to a scene in some way (why run actions on an unattached node, right?). The sprite will be a child of this instance of Palla (a subclassed Sprite node), which we will add as a child to HelloWorldScene -- like you had originally. Then cocos2d-x will happily run the action.
    this->addChild(palla);
    palla->runAction(Rotola());
  } 

  return true;
}

RepeatForever* const Palla::Rotola()
{
  RotateBy* rotazione = RotateBy::create(0.8, 360);
  RepeatForever* AzioneInfinita = RepeatForever::create(rotazione);
  return AzioneInfinita;
}