Omegalisk
Omegalisk

Reputation: 65

C++ - Values change unexpectedly

For some reason, the values of a passed struct change without me accessing them. I found this out by debugging with Visual Studio. Here is the code:

bool Screen::blitSurface(SDL_Surface* src, int x, int y, SDL_Rect* rect) {
  SDL_Rect* offset;
  offset->x = x;
  offset->y = y;

  SDL_BlitSurface( src, rect, screen, offset );

  return true;
}

The struct that is changing is 'rect'. When it is passed, rect->x is 0 and rect->y is 16. However, at the next breakpoint (offset->x = x;) rect->x is a random number (for instance, -13108), same with rect->y. Does anybody have an idea as to why this happens? I'm completely lost, and have no idea where to start.

--EDIT--

Ok, I updated the code to this, but it's still having the problem.

bool Screen::blitSurface(SDL_Surface* src, int x, int y, SDL_Rect* rect) {
  SDL_Rect offset;
  offset.x = x;
  offset.y = y;

  SDL_BlitSurface( src, rect, screen, &offset );

  return true;
}

However, it did get me thinking. If I create a local struct, and return a pointer to it, it is deleted once the function completes? For example, does this work?

SDL_Rect* getRect(int x, int y, int width, int height) {
  SDL_Rect rect;

  rect.x = x;
  rect.y = y;
  rect.w = width;
  rect.h = height;

  return ▭  
}

This is where I get the 'rect' variable that I am passing to 'blitSurface'.

Upvotes: 1

Views: 3214

Answers (2)

Dietrich Epp
Dietrich Epp

Reputation: 213837

This code is wrong:

SDL_Rect* offset;
offset->x = x;
offset->y = y;

Here, offset is an uninitialized pointer. Accessing an uninitialized pointer is always an error, even though it doesn't always crash your program. I wouldn't use a pointer here.

SDL_Rect offset;
offset.x = x;
offset.y = y;
SDL_BlitSurface(src, rect, screen, &offset);

When you access an uninitialized pointer (or an invalid one), you are basically telling your computer to scribble over an arbitrary part of your computer's memory. In a best-case scenario, the program crashes. In a worst-case scenario, it doesn't crash -- think about that for a moment.

This code is also wrong:

SDL_Rect rect;
// ...
return ▭  

The pointer to rect is invalid as soon as the function exits. Again, I wouldn't use a pointer here.

SDL_Rect getRect(int x, int y, int width, int height)
{
    SDL_Rect rect;
    rect.x = x;
    rect.y = y;
    rect.w = width;
    rect.h = height;
    return rect;
}

The SDL_Rect structure is small enough and trivial enough that you should feel free to return it from a function. If you need to pass the result to an SDL function that takes a pointer, do it this way:

SDL_Rect r = getRect(...);

SDL_Some_Function(..., &r, ...);

Pointers are dangerous in C and C++: That's not to say you shouldn't use them. But if you don't know exactly what conditions make a pointer valid or invalid, then your program will be incorrect. The compiler will not help you figure this out -- although static analysis tools like Clang might help.

Unlike C and C++, most other languages (like Python, C#, Java, Haskell, Lisp, Perl, Ruby) do not allow you to create invalid pointers unless you really work at it.

Upvotes: 2

Luchian Grigore
Luchian Grigore

Reputation: 258688

Two words: Undefined behavior.

  SDL_Rect* offset;
  offset->x = x;
  offset->y = y;

You're accessing an uninitialized variable.

Either allocate offset:

SDL_Rect* offset = new SDL_Rect;

or have it in automatic memory:

  SDL_Rect offset;
  offset.x = x;
  offset.y = y;

  SDL_BlitSurface( src, rect, screen, &offset );

Upvotes: 2

Related Questions