繁体   English   中英

我的动态数组在free()时有一个SIGSEGV,但是可以访问吗?

[英]My dynamic array has a SIGSEGV when free()'d, but can be accessed?

最近,我一直难以跟踪细分错误。 奇怪的是,它使我可以很好地访问数组,但是由于某种原因,它不允许我释放它而不引起错误。 我测试了所有内容以确保没有其他内容,因此我可以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。 我认为是导致此问题的一些细微问题,但我不知道这是什么。 我很高兴你们中的任何人比我更了解调试,并且至少可以提出一些建议。

奇怪的是,它使我可以很好地访问数组,但是由于某种原因,它不允许我释放它而不引起错误。

这是不奇怪

大多数UNIX malloc实现不会立即将free d内存释放到OS。 取而代之的是,他们将其保留在空闲列表中,以希望应用程序再次请求它,并且可以在执行系统调用的情况下轻松使用它(这很昂贵)。

令人困惑的是,崩溃是非常有选择性的。

对于堆损坏问题,这也非常典型。 当您破坏堆时(例如,通过分配的缓冲区溢出或free两次),崩溃可能会晚得多,并且当您更改无关的东西时可能会消失。

好消息: ValgrindAddress Sanitizer之类的工具通常可以帮助您快速有效地发现堆损坏问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM