C / SDL - 程序连续多次运行时的分段错误

时间:2015-05-18 10:01:20

标签: c segmentation-fault sdl

我在程序中遇到了一些奇怪的行为。

当我运行我的程序3-4次并立即关闭它时,它会在它开始之前开始给我分段错误。当我没有打开它一段时间它会打开前2-3次没有问题,然后再次出现故障。

我愿意接受可能导致此类问题的建议。 该项目非常大,所以如果有人想查看源代码,我就不知道到底要看哪里,你走了: https://github.com/rokn/Helsys3

1 个答案:

答案 0 :(得分:0)

让我为你打破调试会话,但将来你最好自己做。

如果问题可以轻易复制,修复它是非常简单的:

gdb ./GAME
(gdb) r
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7b2d10c in ?? () from /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0
(gdb) bt
#0  0x00007ffff7b2d10c in ?? () from /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0
#1  0x000000000040650c in sprite_free_age ()
#2  0x00000000004065f9 in AGE_SpriteLoad ()
#3  0x0000000000402740 in BattlefieldLoad () at battlefield.c:89
#4  0x0000000000402794 in BattlefieldInit (battlefield=0x1dca440, battlefieldId=1)
    at battlefield.c:96
#5  0x0000000000405349 in BattleInitialize (leftTeam=0x60dff0 <leftTeam>, 
    rightTeam=0x60e010 <rightTeam>, battlefieldId=1) at battle.c:13
#6  0x0000000000401e8f in LoadContent () at main.c:90
#7  0x0000000000401d2b in main (argc=1, argv=0x7fffffffdfc8) at main.c:49

它在SDL中崩溃,最后一个叫做sprite_free_age的东西。这是什么(AGE/AGE_Sprite.c):

void sprite_free_age(AGE_Sprite *sprite)
{
    if( sprite->texture != NULL )
    {
        SDL_DestroyTexture( sprite->texture );
        sprite->texture = NULL;
        sprite->Width = 0;
        sprite->Height = 0;
    }
}

唯一的SDL调用是SDL_DestroyTexture,并且执行了NULL检查,这意味着sprite具有垃圾数据(不是NULL,但仍然不是SDL纹理,而是其他东西)。它来自AGE_SpriteLoad

bool AGE_SpriteLoad(AGE_Sprite *sprite, char *path)
{
    sprite_free_age(sprite);

    SDL_Texture *finalTexture = NULL;
    SDL_Surface *loadedSurface = IMG_Load(path);

    // ... the rest is omitted

因此,无论何时调用AGE_SpriteLoad,它都会首先尝试删除它可能包含的前一个精灵。它来自BattlefieldLoad的{​​{1}}:

battlefield.c:89

此处您已取消初始化void BattlefieldLoad() { assert(AGE_SpriteLoad(&squareWalkable, "Resources/Battlefield/SquareWalkable.png")); assert(AGE_SpriteLoad(&squareSelected, "Resources/Battlefield/SquareSelected.png")); assert(AGE_SpriteLoad(&squareEnemy, "Resources/Battlefield/SquareEnemy.png")); assert(AGE_SpriteCreateBlank(&battlefieldField, LevelWidth, LevelHeight, SDL_TEXTUREACCESS_TARGET)); AGE_ListInit(&objectsList, sizeof(AGE_Sprite)); AGE_Sprite objectSprite; int i; char buffer[100]; for (i = 0; i < BATTLEFIELD_OBJECTS_COUNT; ++i) { snprintf(buffer, sizeof(buffer), "Resources/Battlefield/Object_%d.png", i+1); AGE_SpriteLoad(&objectSprite, buffer); AGE_ListAdd(&objectsList, &objectSprite); } } ,并且您正在调用AGE_Sprite objectSprite,它会尝试删除旧数据(未初始化=&gt;垃圾)和(可能)崩溃。首先要想到的是,您需要将AGE_SpriteLoad设置为零字节,或者使用objectSprite,或者只需在声明时将其初始化为零,例如memset