【问题标题】:Segmentation fault loading texture with SDL2使用 SDL2 加载纹理的分段错误
【发布时间】:2014-05-11 13:40:38
【问题描述】:

我刚刚使用 SDL 1.2 完成了俄罗斯方块克隆,现在我正在尝试使用 SDL2 制作更好的版本。但是我遇到了分段错误,我不知道为什么。

这是 valgrind 报告:

==9471== Memcheck, a memory error detector
==9471== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==9471== Using Valgrind-3.9.0 and LibVEX; rerun with -h for copyright info
==9471== Command: ./tetris
==9471== 
==9471== Thread 2:
==9471== Invalid read of size 8
==9471==    at 0xB4B57A9: ??? (in /usr/lib/x86_64-linux-gnu/nvidia/current/libGL.so.319.82)
==9471==    by 0x4E8094E: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.1.0)
==9471==    by 0x4E799EA: SDL_CreateTexture (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.1.0)
==9471==    by 0x4E79C6D: SDL_CreateTextureFromSurface (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.1.0)
==9471==    by 0x401176: load_texture.3137.2439 
==9471==    by 0x401194: video_load_image.2436
==9471==    by 0x4011B6: block_image_load_all.2429
==9471==    by 0x4017BD: run_game_logic.2384
==9471==    by 0x541B061: start_thread (pthread_create.c:312)
==9471==    by 0x5715A3C: clone (clone.S:111)
==9471==  Address 0x8c0 is not stack'd, malloc'd or (recently) free'd
==9471== 
==9471== 
==9471== Process terminating with default action of signal 11 (SIGSEGV)
==9471==  Access not within mapped region at address 0x8C0
==9471==    at 0xB4B57A9: ??? (in /usr/lib/x86_64-linux-gnu/nvidia/current/libGL.so.319.82)
==9471==    by 0x4E8094E: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.1.0)
==9471==    by 0x4E799EA: SDL_CreateTexture (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.1.0)
==9471==    by 0x4E79C6D: SDL_CreateTextureFromSurface  (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.1.0)
==9471==    by 0x401176: load_texture.3137.2439
==9471==    by 0x401194: video_load_image.2436
==9471==    by 0x4011B6: block_image_load_all.2429
==9471==    by 0x4017BD: run_game_logic.2384
==9471==    by 0x541B061: start_thread (pthread_create.c:312)
==9471==    by 0x5715A3C: clone (clone.S:111)
==9471==  If you believe this happened as a result of a stack
==9471==  overflow in your program's main thread (unlikely but
==9471==  possible), you can try to increase the size of the
==9471==  main thread stack using the --main-stacksize= flag.
==9471==  The main thread stack size used in this run was 8388608.

以及功能:

SDL_Texture *video_load_image(const char *file)
{
    return load_texture(file);
}

static SDL_Texture *load_texture(const char *path)
{
    SDL_Surface *surface;
    SDL_Texture *texture;

    if((surface = SDL_LoadBMP(path)) == NULL){
        puts("invalid path");
        return NULL;
    }

    texture = SDL_CreateTextureFromSurface(renderer, surface);
    SDL_FreeSurface(surface);

    return texture;
}

char *image_path[BLOCK_COUNT] = {
    "img/block_dark_cyan32.bmp", "img/block_dark_red32.bmp",
    "img/block_dark_brown32.bmp", "img/block_dark_magenta32.bmp",
    "img/block_dark_gray32.bmp", "img/block_dark_green32.bmp",
    "img/block_dark_blue32.bmp", 
    "img/block_wall32.bmp", "img/block_empty32.bmp"
};

SDL_Texture *textures[BLOCK_COUNT];

int block_image_load_all(void)
{
    for(int i = 0; i < BLOCK_COUNT; ++i){
        if((textures[i] = video_load_image(image_path[i])) == NULL){
            while(i > 0)
                video_free_image(textures[--i]);

            return ERROR;
        }
    }

    return SUCCESS;
}

这里是什么导致分段错误?

更新:将渲染器切换到SDL_RENDERER_SOFTWARE 可以解决问题,但我想使用SDL_RENDERER_ACCELERATED

我不认为问题出在驱动程序上,因为我在另一个程序中成功使用了SDL_RENDERER_ACCELERATED

【问题讨论】:

  • 渲染器是否在纹理加载时完全初始化?您确定您的 OpenGL 驱动程序运行正常吗?至少使用glxinfoglxgears 对其进行测试。另外,valgrind 是内存调试器;如果发生崩溃,最好使用像gdb这样的普通调试器(但它与您的问题没有直接关系)
  • @keltar 我相信这与此代码或图像有关,因为 SDL_RENDERER_ACCELERATED 标志在另一个类似项目中正常工作。
  • @keltar 我按照您的建议对两者进行了测试,没有问题。图像格式可能是问题吗?我使用 gimp 创建了块并导出为 ARGB 32 位。
  • 您不会在代码中显示BLOCK_COUNT 的定义 - 如果它超过image_path 中的字符串数,那么您可以使用空指针调用video_load_image
  • @2013Asker 您如何制作完整的可编译的最小示例,包括您有问题的图像之一并将其上传到某个地方?可能有很多原因,但仅凭这些代码片段是不可能的。

标签: c segmentation-fault sdl sdl-2


【解决方案1】:

看起来您没有在代码中释放字体。试试:

TTF_CloseFont(TTF_Font *font);

字体使用完毕后,否则会在几百帧后导致分段错误。

【讨论】:

    【解决方案2】:

    我认为问题不是驱动程序,因为我正在使用 SDL_RENDERER_ACCELERATED 在另一个程序中成功。

    是的,很可能是您的程序而不是库中存在问题。查看 Valgrind 错误报告,您的程序似乎乱七八糟,内存已损坏。这是通过查看您的代码 sn-p 很难找到。您的问题可能有以下三个原因:

    1. 释放内存后堆内存溢出/读取。
    2. 堆栈溢出场景。
    3. 线程中的同步问题导致某种形式的内存损坏。

    所有这些问题都很难识别,除了调试之外,在大型程序中没有分类方法来查找此类错误。您可以参考我之前关于 Valgrind/GDBHelgrind 的帖子。

    https://stackoverflow.com/a/22658693/2724703

    https://stackoverflow.com/a/22617989/2724703

    【讨论】:

      【解决方案3】:

      确保在使用 SDL_CreateRender() 时将 -1 作为第二个参数,以便 SDL 自动选择要使用的有效显卡。

      如果问题仍然存在,请更新您的显卡驱动程序(之后重新启动计算机)。

      如果它仍然存在,请发表评论

      【讨论】:

      • 是的,仍然存在,这不是问题。
      猜你喜欢
      • 2015-04-22
      • 2013-06-03
      • 2014-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-18
      • 1970-01-01
      相关资源
      最近更新 更多