-1
\$\begingroup\$

So, lets start off with the weird Sprite* object sometimes being NULL.

I run my game, the EXC_BAD_ACCESS error comes and sometimes, only sometimes my Sprite* has a value when it crashes.

Sometimes it has a memory address and other times it is just NULL.

Though, even when it has a memory address the game generates the same error.

Here's how I define my Sprite class :

std::map<std::string, Sprite*> sprites;

I use this function to create a new sprite :

void Graphics::CreateSprite(std::string ID, std::string textureID, int x, int y, int width, int height)
{
    std::cout << imagePaths["Square"] << std::endl;
    sprites.insert(std::make_pair(ID, new Sprite(imagePaths[textureID], x, y, width, height, windowRenderer)));
}

And I call it like this :

graphicsManager->CreateSprite("Test", "Square", 32, 32, 100, 50);

And if I std::cout the sprite using this GetSprite function ( to get the memory address, so I can check if it's NULL) :

Sprite* Graphics::GetSprite(std::string spriteID)
{
    std::map<std::string,Sprite*>::iterator it;
    it = sprites.find("Square");
    return it->second;
}

Calling it like this :

std::cout << graphicsManager->GetSprite("Test") << std::end;

I get the output of a memory address so the Sprite is not NULL.


Now, to the weird values in my SDL_Rect.

The SDL_Rec is defined like this :

SDL_Rect m_rect;

Initialised like this : (in the constructor of the Sprite class)

m_rect.x = x;
m_rect.y = y;

if (width == 0)
{
    m_rect.w = textureSurface->w;
}
else {
    m_rect.w = width;
}

if (height == 0)
{
    m_rect.h = textureSurface->h;
}
else {
    m_rect.h = height;
}

The parameters being :

Sprite::Sprite(std::string imgPath, int x, int y, int width, int height, SDL_Renderer* windowRenderer)

Which is called when you create the sprite using the function I posted above.

The values in this case should be :

x axis : 32

y axis : 32

width : 100

height : 50

However, when I check the values they are :

x axis : -1869611001

y axis : -1869574000

width : -443987883

height : 1889462621

They are like this before the game crashes as well.


And now onto the actual crash of my game :

The error looks like this :

Thread 1: EXC_BAD_ACCESS (code=1 address=0x7)

And the error is created on this line when I try to give my m_rect (SDL_Rect) a value :

void Sprite::Move(int offsetX, int offsetY)
{
    m_rect.x += offsetX;  <--- error here!
    m_rect.y += offsetY;
}

And the Move function is called like this :

graphicsManager->GetSprite("Test")->Move(1, 1);

Right after I create the Sprite using the CreateSprite function.


Edit 1

I played around with the diagnostics tools on the scheme thing, checked malloc, NSZombies objects and such, however none of them worked so I disabled all of them and tried again.

Suddenly my application didn't crash???

However when I tried running it right after, it once again crashed?

I'm so confused...


Edit 2

So, the next day everything started working again with no modifications to the code.

Now I'm even more confused. lol

\$\endgroup\$
4
  • 1
    \$\begingroup\$ Did you use a step-by-step debugger to validated all the calls and all the objects are valid? EXC_BAD_ACCESS looks like you're using a non valid object. \$\endgroup\$
    – Vaillancourt
    Mar 11, 2016 at 22:26
  • \$\begingroup\$ What does your texture/sprite map look like in the debugger? You might be using wrong key values somewhere. \$\endgroup\$
    – user35344
    Mar 11, 2016 at 22:40
  • \$\begingroup\$ @AlexandreVaillancourt Somehow, everything started working the next day, without any modifications to the code. \$\endgroup\$
    – BiiX
    Mar 12, 2016 at 8:29
  • 1
    \$\begingroup\$ In addition to my answer, I suggest you change the signature of the method Sprite* Graphics::GetSprite(std::string spriteID) to Sprite* Graphics::GetSprite(const std::string& spriteID) to avoid a useless string copy :) \$\endgroup\$
    – Vaillancourt
    Mar 12, 2016 at 23:15

1 Answer 1

4
\$\begingroup\$

There is a code smell here:

Sprite* Graphics::GetSprite(std::string spriteID)
{
    std::map<std::string,Sprite*>::iterator it;
    it = sprites.find("Square");
    return it->second;
}

By not making sure that the object is valid, the it could be sprites.end(). According to some documentation, it's very dangerous to dereference the end() iterator. You can't be sure that the ->second part will be nullptr (in fact, you can be sure that it will not be nullptr; it will be garbage, that's c++).

Also, you're not using the parameter you pass to the function:

To fix this, modify your code:

Sprite* Graphics::GetSprite(std::string spriteID)
{
    std::map<std::string,Sprite*>::iterator it;
    it = sprites.find(spriteID);
    if( it != sprites.end() )
      return it->second;

    return nullptr;
}
\$\endgroup\$
1
  • \$\begingroup\$ My application randomly started working again today with no modifications to the code... However I will add this to the code. \$\endgroup\$
    – BiiX
    Mar 12, 2016 at 8:19

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .