取消引用指向 size_t 的指针,但从 void 指针转换
Dereferencing a pointer to size_t, but cast from void pointer
基本上,我将用户生成的事件推送到 SDL 事件队列中。在这样做时,我将一个整数的地址推送到一个 void 指针上,该指针是 SDL_PushEvent().
的 data1 参数
稍后,我尝试取消引用从队列中获取的事件中的 void 指针。但是,当我这样做时,我应该得到的值 (1002) 与我实际得到的值相去甚远:140733847900856.
我最初是从 void 指针转换为整数指针。 las,我在 64 位架构上,所以我不得不使用 size_t。但我对 size_t 用法并不完全熟悉,所以我可能做错了什么。
这是来自两个不同源文件的代码片段:
来自 "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;
}
来自 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;
以下是我实际 运行 程序时来自 cerr 的结果:
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
(注意:我知道是什么导致了 运行 下的缓冲区,以及如何解决它。不过,我想先解决这个取消引用问题,所以不用担心。:D)
感谢您的宝贵时间。
您的 data1
,这是您存储在 tmp.user.data1 中的 地址 的对象 对于 if.
因此它会在退出块时被销毁,你将留下一个悬空指针。
您可能希望使用 new
.
在堆上分配 data1
在splash.cpp
中你定义了一个分配在栈上的新变量size_t data1 = MAIN_MENU_MODE;
。然后将其地址存储到 tmp.user.data1
。当 size_t data1
超出 splash.cpp
的范围时,它会被自动删除。
当 event->user.data1
在 events.cpp
中被取消引用时,您会得到当时堆栈中该地址中的任何内容。该指针称为 dangling pointer 并且取消引用会导致未定义的行为。在您的情况下,您会得到一个 "random" 数字。通常,您会遇到分段错误。
您可能想在堆上分配此变量以用于您尝试执行的操作,例如
size_t *data1 = new size_t(MAIN_MENU_MODE);
当你不再需要它时记得删除它!
基本上,我将用户生成的事件推送到 SDL 事件队列中。在这样做时,我将一个整数的地址推送到一个 void 指针上,该指针是 SDL_PushEvent().
的 data1 参数稍后,我尝试取消引用从队列中获取的事件中的 void 指针。但是,当我这样做时,我应该得到的值 (1002) 与我实际得到的值相去甚远:140733847900856.
我最初是从 void 指针转换为整数指针。 las,我在 64 位架构上,所以我不得不使用 size_t。但我对 size_t 用法并不完全熟悉,所以我可能做错了什么。
这是来自两个不同源文件的代码片段:
来自 "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;
}
来自 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;
以下是我实际 运行 程序时来自 cerr 的结果:
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
(注意:我知道是什么导致了 运行 下的缓冲区,以及如何解决它。不过,我想先解决这个取消引用问题,所以不用担心。:D)
感谢您的宝贵时间。
您的 data1
,这是您存储在 tmp.user.data1 中的 地址 的对象 对于 if.
因此它会在退出块时被销毁,你将留下一个悬空指针。
您可能希望使用 new
.
data1
在splash.cpp
中你定义了一个分配在栈上的新变量size_t data1 = MAIN_MENU_MODE;
。然后将其地址存储到 tmp.user.data1
。当 size_t data1
超出 splash.cpp
的范围时,它会被自动删除。
当 event->user.data1
在 events.cpp
中被取消引用时,您会得到当时堆栈中该地址中的任何内容。该指针称为 dangling pointer 并且取消引用会导致未定义的行为。在您的情况下,您会得到一个 "random" 数字。通常,您会遇到分段错误。
您可能想在堆上分配此变量以用于您尝试执行的操作,例如
size_t *data1 = new size_t(MAIN_MENU_MODE);
当你不再需要它时记得删除它!