0

Basically, I'm pushing a user generated event onto an SDL event queue. In doing this, I push the address of an integer onto a void pointer which is the data1 parameter of SDL_PushEvent().

Later, I attempt to dereference the void pointer in the event fetched from the queue. When I do so, however, the value I'm supposed to get(1002) is nowhere near the value I actually do get: 140733847900856.

I was originally converting from a void pointer to an integer pointer. Alas, I'm on a 64-bit architecture, so I had to use size_t. But I'm not entirely familiar with size_t usage, so I'm probably doing something wrong.

Here's the code snippets, from two different source files:

from "splash.cpp":

  if(elapsed >= 13000 && !(flag)){
    std::cerr << "13 seconds elapsed.\n";

    // Create and push a CHANGE_GAME_MODE event to the queue.
    SDL_Event tmp;
    size_t data1 = MAIN_MENU_MODE;

    tmp.type=SDL_USEREVENT;
    tmp.user.code= CHANGE_GAME_MODE;
    tmp.user.data1 = &data1;
    tmp.user.data2 = NULL; // Not used.

    std::cerr << "Value of data1 before SDL_PushEvent():"
              << *((size_t*)(tmp.user.data1)) << "\n";

    SDL_PushEvent(&tmp);
    flag = true;
  }

from events.cpp:

  case SDL_USEREVENT:
    std::cerr << "\nUser event detected: " << *((size_t*)(event->user.data1)) << "\n";
    user_event(event->user.type, event->user.code, event->user.data1, event->user.data2);
    break;

Here are the results from cerr when I actually run the program:

sysadm@druid: ./kolodruidtale 
ALSA lib pcm.c:7843:(snd_pcm_recover) underrun occurred
13 seconds elapsed.
Value of data1 before SDL_PushEvent():1002

User event detected: 140688563309902
ALSA lib pcm.c:7843:(snd_pcm_recover) underrun occurred

(Note: I'm aware of what is causing the buffer underrun, and how to fix it. I want to get this dereferencing issue fixed first, though, so no worries. :D)

Thank you for your time.

Druid
  • 133
  • 3
  • 12
  • 1
    You really should use `std::intptr_t` instead of `std::size_t`. See http://stackoverflow.com/questions/1464174/size-t-vs-intptr-t. – Captain Obvlious Sep 20 '15 at 16:37
  • 2
    possible duplicate of [Can a local variable's memory be accessed outside its scope?](http://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope) – NathanOliver Sep 20 '15 at 16:50

2 Answers2

1

In splash.cpp you define a new variable size_t data1 = MAIN_MENU_MODE; that is allocated on the stack. Then you store its address to tmp.user.data1. When size_t data1 goes out of scope in splash.cpp it gets automatically deleted.

When event->user.data1 is dereferenced in events.cpp you get whatever happens to be in this address on the stack at that moment. This pointer is called a dangling pointer and dereferencing results in undefined behaviour. In your case you get a "random" number as a result. Normally, you get a segmentation fault.

You probably want to allocate this variable on the heap for what you are trying to do e.g.

size_t *data1 = new size_t(MAIN_MENU_MODE);

and remember to delete it when you no longer need it!

Manos Nikolaidis
  • 21,608
  • 12
  • 74
  • 82
  • Ah, there it was! Thank you very, very much, Manos Nikolaidis! This makes me very happy. (^.^) – Druid Sep 20 '15 at 18:56
0

Your data1, which is the object whose address you are storing in tmp.user.data1 is local to the if.

Therefore it will be destroyed upon exiting the block, and you will be left with a dangling pointer.

You might want to allocate your data1 on the heap instead, using new.

danielschemmel
  • 10,885
  • 1
  • 36
  • 58