gpt4 book ai didi

c++ - 我的动态数组在 free() 时有 SIGSEGV,但可以访问吗?

转载 作者:行者123 更新时间:2023-11-30 17:41:31 28 4
gpt4 key购买 nike

我最近遇到了难以追踪段错误的问题。奇怪的是,它让我可以很好地访问数组,但由于某种原因,它不允许我在不导致错误的情况下释放它。我测试了所有内容以确保不是其他任何问题,因此我可以 100% 肯定地说它只发生在空闲线路上。令人困惑的是,崩溃是非常有选择性的。例如,它仅在我按下游戏菜单上的帮助按钮后才会发生,但除此之外没有任何问题。访问帮助部分后,它仍然允许访问,这使得错误更加奇怪。我可能对段错误有错误的想法,但我很确定他们通常不会允许访问,即使这不是一个重大错误。我知道他们通常不适合我。我会在这里发布代码,但我的项目非常大。我会尝试发布重要的部分。

这是我分配数组的方法:

static void zero_array( void * memory, int elements, size_t element_size )
{
memset( memory, 0, elements * element_size );

return;
}

/* ******************************************************** */

static void fill_array_with_ones( void * memory, int elements, size_t element_size )
{
memset( memory, 1, elements * element_size );

return;
}

/* ******************************************************** */

static void * create_array( int elements, size_t element_size, t_setter setter )
{
void * temp = NULL;

if ( !( temp = malloc( elements * element_size ) ) )
{
perror( "malloc" );
exit( 1 );
}

if ( setter )
setter( temp, elements, element_size );

return temp;
}

我已经测试过很多次了,没有任何问题。我主要将它用于我的菜单 API,以便更轻松地跟踪位图图像上 SDL 中的按钮事件。

我的问题区域设置代码如下所示:

extern void setup_mdata( game_data * game, menu * tmenu, const char * menu_image_path, int max_buttons, bool default_handling, t_handle_var_mdata handle_mdata )
{
int width = 0;
int height = 0;

tmenu->max_buttons = max_buttons;
tmenu->allocation_size = sizeof( bool ) * game->game_menu.max_buttons;

tmenu->hover_over_button = ( bool * )create_array( max_buttons, sizeof( bool ), zero_array );
tmenu->is_clicked = ( bool * )create_array( max_buttons, sizeof( bool ), zero_array );
if ( !default_handling )
tmenu->is_enabled = ( bool * )create_array( max_buttons, sizeof( bool ), fill_array_with_ones );
tmenu->button_shape = ( SDL_Rect * )create_array( max_buttons, sizeof( SDL_Rect ), zero_array );

tmenu->menu_image = load_texture( game->renderer, ( char * )menu_image_path, true, 255, 0, 255 );
SDL_QueryTexture( game->game_menu.menu_image, NULL, NULL, &width, &height );

handle_mdata( game, tmenu, width, height );

return;
}

我已经多次测试了这段代码,并且在任何其他菜单上都没有失败过。这让这个问题对我来说很奇怪。

以下是我如何为标题屏幕的主菜单和帮助菜单调用此函数:

setup_mdata( game, &game->title_menu, "bitmaps//title_menu.bmp", 3, true, setup_title_menu );
setup_mdata( game, &game->title_help_menu, "bitmaps//title_help_menu.bmp", 3, true, setup_title_help_menu );

我认为这并不重要,但如果您想知道,这里是使用附加数据实际设置菜单的代码。

static void setup_title_menu( game_data * game, menu * tmenu, int width, int height )
{
int nbutton = 0;

tmenu->button_highlight = ( SDL_Texture ** )create_array( 1, sizeof( SDL_Texture * ), zero_array );
*tmenu->button_highlight = load_texture( game->renderer, ( char * )"bitmaps//button4_highlight.bmp", true, 255, 255, 255 );

for ( ; nbutton < tmenu->max_buttons; nbutton++ )
{
MB_SHAPE.h = TITLE_BUTTON_HEIGHT;
MB_SHAPE.w = TITLE_BUTTON_WIDTH;
MB_SHAPE.x = menu_shape.x + FIRST_TITLE_BUTTON_X;
MB_SHAPE.y = menu_shape.y + FIRST_TITLE_BUTTON_Y + ( ( TITLE_BUTTON_HEIGHT + TITLE_BUTTON_DIVIDER_HEIGHT ) * nbutton );
}

return;
}

/* ******************************************************** */

static void setup_title_help_page_shape( game_data * game )
{
game->title_screen_data.help_page_shape.h = HELP_PAGE_HEIGHT;
game->title_screen_data.help_page_shape.w = HELP_PAGE_WIDTH;
game->title_screen_data.help_page_shape.x = menu_shape.x + 59;
game->title_screen_data.help_page_shape.y = menu_shape.y + 192;

return;
}

/* ******************************************************** */

static void setup_title_help_menu( game_data * game, menu * tmenu, int width, int height )
{
int nbutton = 0;

tmenu->button_highlight = ( SDL_Texture ** )create_array( 2, sizeof( SDL_Texture * ), zero_array );
tmenu->button_highlight[0] = load_texture( game->renderer, ( char * )"bitmaps//button2_highlight.bmp", true, 255, 255, 255 );
tmenu->button_highlight[1] = load_texture( game->renderer, ( char * )"bitmaps//triangle_highlight.bmp", true, 255, 255, 255 );

setup_title_help_page_shape( game );

for ( ; nbutton < tmenu->max_buttons; nbutton++ )
{
switch ( nbutton )
{
case GO_BACK :
tmenu->button_shape[GO_BACK].h = 50;
tmenu->button_shape[GO_BACK].w = 120;
tmenu->button_shape[GO_BACK].x = menu_shape.x + 329;
tmenu->button_shape[GO_BACK].y = menu_shape.y + 61;
break;

case ARROW_RIGHT :
tmenu->button_shape[ARROW_RIGHT].h = 34;
tmenu->button_shape[ARROW_RIGHT].w = 17;
tmenu->button_shape[ARROW_RIGHT].x = menu_shape.x + 432;
tmenu->button_shape[ARROW_RIGHT].y = menu_shape.y + 473;
break;

case ARROW_LEFT :
tmenu->button_shape[ARROW_LEFT].h = 34;
tmenu->button_shape[ARROW_LEFT].w = 17;
tmenu->button_shape[ARROW_LEFT].x = menu_shape.x + 390;
tmenu->button_shape[ARROW_LEFT].y = menu_shape.y + 473;
break;
}
}

return;
}

它真正崩溃的部分是当我尝试这样做时:

free( game->title_help_menu.is_clicked );
free( game->title_help_menu.hover_over_button );

如果您想知道,无论出于何种原因,它都不会破坏帮助菜单数组。这让我更加困惑。我通过删除这些函数来确保它不是其他任何东西,并且它没有抛出 SIGSEGV。我认为有一些微妙的问题导致了这种情况,但我不知道它是什么。如果你们中有人比我更了解调试,并且至少可以就此提出一些建议,我很高兴。

最佳答案

The strange thing is, it lets me access the array fine, but for some reason it doesn't allow me to free it without causing the fault.

这一点也不奇怪。

大多数 UNIX malloc 实现不会立即将空闲内存释放给操作系统。相反,他们将其保留在空闲列表中,希望应用程序会再次请求它,并且它可以随时可用,而无需执行系统调用(这是昂贵的)。

The confusing thing is that the crash is very selective.

这也是堆损坏问题的典型情况。当您损坏堆时(例如,通过溢出分配的缓冲区,或两次释放某些内容),崩溃可能会晚得多,并且当您更改不相关的内容时可能会消失。

好消息:像Valgrind这样的工具和 Address Sanitizer通常可以帮助您非常快速有效地发现堆损坏问题。

关于c++ - 我的动态数组在 free() 时有 SIGSEGV,但可以访问吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21068166/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com