【问题标题】:C/SDL - Segmentation fault when program run multiple times in succession [closed]C / SDL - 程序连续多次运行时出现分段错误[关闭]
【发布时间】:2015-05-18 10:01:19
【问题描述】:

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

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

我愿意就可能导致此类问题的原因提出建议。 这个项目很大,所以我不知道在哪里看,所以如果有人想看源代码,你去: https://github.com/rokn/Helsys3

【问题讨论】:

  • 你需要使用调试器,伙计
  • 寻求调试帮助的问题(“为什么这段代码不起作用?”)必须包括所需的行为、特定的问题或错误以及在问题本身中重现它所需的最短代码。没有明确问题陈述的问题对其他读者没有用处。请参阅:How to create a Minimal, Complete, and Verifiable example
  • 投票结束。您必须自己将问题缩小到一段独立的、可编译的代码。

标签: c segmentation-fault sdl


【解决方案1】:

让我为你分解一个调试会话,但以后你最好自己做。

如果问题可以很容易地重现,修复它是很简单的:

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,它都会首先尝试删除它可能包含的先前精灵。它是从BattlefieldLoadbattlefield.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,你在上面调用AGE_SpriteLoad,它试图删除旧数据(这是未初始化的=>垃圾)和(可能)崩溃。首先想到的是,您需要将objectSprite 设置为零字节,可以使用memset 或仅在声明时对其进行初始化,例如AGE_Sprite objectSprite = {};.

【讨论】:

  • 谢谢。我实际上知道如何使用调试器,但出于某种原因,我突然想到实际上有一个调试器。如果我没有忘记,我可能会发现问题出在这个变量上,但我仍然不知道它实际上包含垃圾数据,所以感谢您澄清这一点。
猜你喜欢
  • 2021-07-18
  • 2019-03-27
  • 2013-11-30
  • 2013-09-13
  • 2023-04-08
  • 1970-01-01
  • 1970-01-01
  • 2015-03-20
相关资源
最近更新 更多