【发布时间】:2017-08-17 11:30:31
【问题描述】:
我在 MacOS 10.12 上使用 Xcode 8.3.3 并通过 Homebrew 作为 Dylib 安装了 SDL2。
以下是稍作修改的sample code from lazy foo。
我刚刚添加了第二个纹理 gTexture2 和函数 loadMedia2 以便能够重现该问题。第二次执行 IMG_Load 时,它会崩溃并显示以下消息:
EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
搜索如何解决“一般保护错误”问题也没有让我进一步了解,崩溃似乎发生在 SDL 内部。我可能在这里真的误解了导致这个问题的东西,并且真的欢迎任何帮助。
真正令人困惑的是,它并不总是崩溃,只有大约 3 次中的 2 次。
崩溃似乎发生在SDL_AllocFormat_REAL ()内部:
这是代码示例。
/*This source code copyrighted by Lazy Foo' Productions (2004-2015)
and may not be redistributed without written permission.*/
//Using SDL, SDL_image, standard IO, and strings
#include <SDL.h>
#include <SDL_image.h>
#include <stdio.h>
#include <string>
//Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
//Starts up SDL and creates window
bool init();
//Loads media
bool loadMedia();
//Frees media and shuts down SDL
void close();
//Loads individual image as texture
SDL_Texture* loadTexture( std::string path );
//The window we'll be rendering to
SDL_Window* gWindow = NULL;
//The window renderer
SDL_Renderer* gRenderer = NULL;
//Current displayed texture
SDL_Texture* gTexture = NULL;
SDL_Texture* gTexture2 = NULL;
bool init()
{
//Initialization flag
bool success = true;
//Initialize SDL
if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
{
printf( "SDL could not initialize! SDL Error: %s\n", SDL_GetError() );
success = false;
}
else
{
//Set texture filtering to linear
if( !SDL_SetHint( SDL_HINT_RENDER_SCALE_QUALITY, "1" ) )
{
printf( "Warning: Linear texture filtering not enabled!" );
}
//Create window
gWindow = SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );
if( gWindow == NULL )
{
printf( "Window could not be created! SDL Error: %s\n", SDL_GetError() );
success = false;
}
else
{
//Create renderer for window
gRenderer = SDL_CreateRenderer( gWindow, -1, SDL_RENDERER_ACCELERATED );
if( gRenderer == NULL )
{
printf( "Renderer could not be created! SDL Error: %s\n", SDL_GetError() );
success = false;
}
else
{
//Initialize renderer color
SDL_SetRenderDrawColor( gRenderer, 0xFF, 0xFF, 0xFF, 0xFF );
//Initialize PNG loading
int imgFlags = IMG_INIT_PNG;
if( !( IMG_Init( imgFlags ) & imgFlags ) )
{
printf( "SDL_image could not initialize! SDL_image Error: %s\n", IMG_GetError() );
success = false;
}
}
}
}
return success;
}
bool loadMedia()
{
//Loading success flag
bool success = true;
//Load PNG texture
gTexture = loadTexture( "../assets/player.png" );
if( gTexture == NULL )
{
printf( "Failed to load texture image!\n" );
success = false;
}
return success;
}
bool loadMedia2()
{
//Loading success flag
bool success = true;
//Load PNG texture
gTexture2 = loadTexture( "../assets/scene_main/background.png" );
if( gTexture == NULL )
{
printf( "Failed to load texture image!\n" );
success = false;
}
return success;
}
void close()
{
//Free loaded image
SDL_DestroyTexture( gTexture );
SDL_DestroyTexture( gTexture2 );
gTexture = NULL;
gTexture2 = NULL;
//Destroy window
SDL_DestroyRenderer( gRenderer );
SDL_DestroyWindow( gWindow );
gWindow = NULL;
gRenderer = NULL;
//Quit SDL subsystems
IMG_Quit();
SDL_Quit();
}
SDL_Texture* loadTexture( std::string path )
{
//The final texture
SDL_Texture* newTexture = NULL;
//Load image at specified path
SDL_Surface* loadedSurface = IMG_Load( path.c_str() );
if( loadedSurface == NULL )
{
printf( "Unable to load image %s! SDL_image Error: %s\n", path.c_str(), IMG_GetError() );
}
else
{
//Create texture from surface pixels
newTexture = SDL_CreateTextureFromSurface( gRenderer, loadedSurface );
if( newTexture == NULL )
{
printf( "Unable to create texture from %s! SDL Error: %s\n", path.c_str(), SDL_GetError() );
}
//Get rid of old loaded surface
SDL_FreeSurface( loadedSurface );
}
return newTexture;
}
int main( int argc, char* args[] )
{
//Start up SDL and create window
if( !init() )
{
printf( "Failed to initialize!\n" );
}
else
{
//Load media
if( !loadMedia() || !loadMedia2() )
{
printf( "Failed to load media!\n" );
}
else
{
//Main loop flag
bool quit = false;
//Event handler
SDL_Event e;
//While application is running
while( !quit )
{
//Handle events on queue
while( SDL_PollEvent( &e ) != 0 )
{
//User requests quit
if( e.type == SDL_QUIT )
{
quit = true;
}
}
//Clear screen
SDL_RenderClear( gRenderer );
//Render texture to screen
SDL_RenderCopy( gRenderer, gTexture, NULL, NULL );
//Update screen
SDL_RenderPresent( gRenderer );
}
}
}
//Free resources and close SDL
close();
return 0;
}
小更新:
我已经在 windows 上试过了,它运行得很好。所以我猜这个问题与MacOs有关。
我已经尝试重新安装所有库。
- 我使用的是 C++14。
解决方案
好吧,它只是解决方案的一半,它更像是一个解决方法。
感谢@Sahib Yar,他指出尝试将图像放在同一目录中。这解决了这个问题。
但我觉得这真的很奇怪,你应该可以从不同的目录或至少子目录加载资源。
最后一个问题
现在我真的很想解释为什么我们不能在 MacOS 上使用 SDL 从多个目录加载图像。这只是一个错误,已知的事情还是我犯了一个大错误?
【问题讨论】:
-
SDL_image 在 MacOS 上使用ImageIO 来加载图像,因此这可能解释了与 Windows 的不同行为。
-
loadImage2 检查有误。除此之外,这段代码似乎还不错。可能是 SDL 编译错误或 SDL 编译与 ImageIO / OSX 库之间不兼容?