Assigned SDL_Texture pointer is "NULL" after function returns

Hey,
I’m having an issue with a SDL_Texture pointer:

#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <assert.h>

const int WIDTH = 1024;
const int HEIGHT = 768;

SDL_Window* window = NULL;
SDL_Surface* screenSurface = NULL;
SDL_Renderer* renderer = NULL;

void init(SDL_Texture* bg) {
  assert(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) == 0);
  window = SDL_CreateWindow("SDL Test", SDL_WINDOWPOS_UNDEFINED,
                            SDL_WINDOWPOS_UNDEFINED, WIDTH, HEIGHT,
                            SDL_WINDOW_SHOWN);

  renderer = SDL_CreateRenderer(
      window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
  assert(renderer);
  assert(window);

  // This doesn't work
  screenSurface = SDL_GetWindowSurface(window);
  SDL_Surface* loadedSurface = IMG_Load("bg.png");
  assert(loadedSurface);
  SDL_GetError();
  bg = SDL_CreateTextureFromSurface(renderer, loadedSurface);
  fprintf(stdout,"%s\n", SDL_GetError());
  assert(bg);
  SDL_FreeSurface(loadedSurface);
}

int main(int argc, char* argv[]) {
  SDL_Texture* bg = NULL;
  init(bg);
  assert(bg);

  /*
  screenSurface = SDL_GetWindowSurface(window);
  SDL_Surface* loadedSurface = IMG_Load("bg.png");
  assert(loadedSurface);
  bg = SDL_CreateTextureFromSurface(renderer, loadedSurface);
  assert(bg);
  SDL_FreeSurface(loadedSurface);
  */

  while (1) {
    // set clearing color
    SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF);
    SDL_RenderClear(renderer);

    SDL_RenderCopy(renderer, bg, NULL, NULL);

    SDL_RenderPresent(renderer);
  }

  SDL_FreeSurface(screenSurface);
  SDL_DestroyWindow(window);
  SDL_Quit();
  return 0;
}

Why can’t I “keep” my texture? If I step in gdb the pointer gets an address but when the function returns it is NULL If I run the same code in main() it works…

Cheers!

You need to pass the texture as ** "ref"or change the function to be SDL_Texture* init()
tex = init();

Basically your passing your pointer tex* as a copy and not a reference.

void somefunction(int x) {
    x = 100;
};

int main () {
    int value = 1;
    somefunction(value)
    // value doesnt change to 100
    // as its passed by copy
}

You defined your surface as a local variable in the init function. What do you expect to happen after that function returns?

When you’re using: void init(SDL_Texture* bg), you’re passing a copy of the pointer to the SDL_Texture, instead of pointing to it. In a confusing nutshell, the program creates another pointer and copies the data from the old one. If you do: void init(SDL_Texture** bg) and then add: *bg = SDL_CreateTextureFromSurface(renderer, loadedSurface);, and init(&bg); it should start working the way you want. You basically still create the copy, but it then points to your pointer properly.

Smiles’ way is to simply have your init function return the pointer directly. void init(SDL_Texture* bg) becomes: SDL_Texture *init() and you’ll need to add a return call: return bg;, and change: init(bg); to bg = init();

Welcome to the nightmares of pointers wonderful world of pointers.

1 Like

Ah, yes. I see. Cheers guys!

By the way, your assert calls will dissapear when you stop using debugging, (defining NDEBUG). Assert.h Wiki.