【问题标题】:Strange behaviour with executable using SDL library使用 SDL 库的可执行文件的奇怪行为
【发布时间】:2014-02-15 06:05:42
【问题描述】:

我使用 SDL 构建了一个太空入侵者克隆并使用 MSVC11 编译。该代码加载了 4 个单独的 PNG 文件和一个 TTF 字体以用于渲染。当给定一个绝对文件路径(例如“C:/spaceinvader.png”)时,该程序工作得非常好。

我尝试将其更改为相对文件路径,即“./res/spaceinvader.png”

然后程序在发布模式下编译,并将其放置在自己的文件夹中。

目录结构:

game\game.exe
game\(all the required SDL dlls)
game\res\image1.png (and the other 3 images)
game\res\font.ttf

当您尝试运行游戏时会发生最奇怪的事情。第一次尝试运行它时,程序控制台会加载,SDL 窗口打开,然后它会崩溃到桌面。 (我确保 main() 中没有过早的返回码)。然而,在随后的所有时间里,程序都会加载并运行,尽管其中一个精灵没有显示在屏幕上。控制台中出现的唯一错误与两个 sRGB 配置文件不正确的 PNG 文件有关。

如果整个文件夹移动到不同的位置,程序第一次不会再次加载,但随后会加载

所以我的问题是

1) 为什么程序不是第一次加载,而是随后加载? 2) 为什么只有一个精灵无法显示,当文件都相同(在 photoshop 中创建)并且加载它们的代码相同时?

(很抱歉这里没有包含任何代码,因为我不认为这是一个编码问题 - 很高兴根据要求粘贴特定的代码段)

谢谢! 克

编辑:

图片加载代码(loadTexture函数抄自here:

SDL_Texture* loadTexture(const std::string &file, SDL_Renderer *ren)
{
SDL_Texture *texture = IMG_LoadTexture(ren, file.c_str());
    log_CheckSDLPointer(std::cout, texture, "LoadTexture");

return texture;
}

int Gamestate::initialiseSprites(SDL_Renderer *Renderer)
{

enemytexture = loadTexture("./res/invader.png", Renderer);
    if (enemytexture == nullptr) {return 1;}

playertexture = loadTexture("./res/player.png", Renderer);
    if (playertexture == nullptr) {return 1;}

missiletexture = loadTexture("./res/bullet.png", Renderer);
    if (missiletexture == nullptr) {return 1;}

background = loadTexture("./res/background.png", Renderer);
   if (background == nullptr) {return 1;}

return 0;
}

这个函数在main中被调用:

if (Active_Gamestate.initialiseSprites(mainRenderer) != 0)
{
    return 1;  //quit game if sprites could not be initialised
}

【问题讨论】:

  • 您应该做的第一件事是确保对所有可能失败的函数调用进行适当的错误处理。当您拥有它时,他们例如将消息打印到标准输出,然后尝试从命令行运行,看看你得到了什么错误。如果这没有帮助,请复制调试文件夹中的目录结构,并在调试器中运行以捕获崩溃。如果 that 没有帮助,您很可能使用了未初始化的变量(可能是指针)并且需要查看您的代码以找到这些位置。
  • 您的“第一次运行崩溃,后续运行有效”行为可能表明 Windows 的容错堆正在采取措施并应用 shim(这可以解释为什么如果您移动它会再次崩溃) exe) - 见:stackoverflow.com/questions/1041550/… - 基本上你在某个地方有一个讨厌的错误,但 Windows 会自动为你修补它。如果是这种情况,要修复它,您需要查找 FTH 注册表项(在 reg 中搜索您的 exe 名称)并将其删除,然后使用调试器逐步完成。
  • 如果您通过 VS 启动,您还会在“输出”窗口中看到类似的内容: FTH: (9556): *** 应用于当前进程的容错堆 shim。这通常是由于以前的崩溃造成的。 ***
  • 谢谢!我已经添加了图像加载的代码。如果调用失败,所有调用的 SDL 函数都将输出到 std::cout。编译器在 IDE 调试器中运行时不会出现任何错误或警告,并且此行为仅在运行独立 exe 时发生。
  • @KK,这仍然是构建输出 - 你想在调试器中运行应用程序,然后在输出窗格中,确保它显示“显示输出:调试” - 你应该看到很多有关正在加载的 dll 和符号的消息 - 如果有 FTH 消息,则会出现在此处。

标签: c++ visual-studio sdl


【解决方案1】:

感谢所有帮助。我想我已经弄清楚发生了什么。如果图片加载代码改成如下:

char executablePath[FILENAME_MAX];

std::stringstream invaderpathstream;
invaderpathstream << executablePath << "/res/invader.png";
std::string invaderpath = invaderpathstream.str();

enemytexture = loadTexture(invaderpath, Renderer);
if (enemytexture == nullptr) 
     {return 1;}

问题消失了。也许问题出在相对路径(至少在我的系统上),也许在程序第一次运行之后,操作系统以某种方式找到了所需的文件,这就是为什么它在后续运行中顺利运行的原因?

K

【讨论】:

    猜你喜欢
    • 2012-09-02
    • 2015-09-29
    • 1970-01-01
    • 1970-01-01
    • 2012-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-19
    相关资源
    最近更新 更多