C语言SDL2结合Emscripten向HTML5 canvas写文字出现段错误如何解决
问题根因
你的代码存在3个直接触发段错误的核心问题:
- 纹理提前销毁:
set_font_texture函数中刚创建完文字纹理就调用SDL_DestroyTexture销毁了该资源,后续mainLoop访问ctx->text_texture时操作的是野指针。 - TTF子系统提前终止:
get_font_texture执行完逻辑后直接调用了TTF_CloseFont和TTF_Quit,提前释放了字体资源、终止了TTF相关能力,后续所有文字渲染相关操作都会触发非法访问。 - 字体文件未打包进虚拟文件系统:Emscripten默认不会读取本地文件系统的资源,你没有把字体目录打包到WASM的虚拟文件系统中,
TTF_OpenFont会返回空指针,操作空指针直接触发崩溃。
修复步骤
- 修改
set_font_texture函数,删除提前销毁纹理的代码,新增旧纹理释放逻辑避免内存泄漏:
void set_font_text(struct Context *ctx, const char *text) { // 先销毁旧纹理,避免内存泄漏 if (ctx->text_texture) { SDL_DestroyTexture(ctx->text_texture); ctx->text_texture = NULL; } SDL_Color fg = {0,0,0,255}; SDL_Surface *text_surface = TTF_RenderText_Blended(ctx->font, text, fg); // 新增错误判断,避免表面创建失败后续操作崩溃 if (!text_surface) { printf("创建文字表面失败: %s\n", TTF_GetError()); return; } ctx->text_texture = SDL_CreateTextureFromSurface(ctx->renderer, text_surface); SDL_FreeSurface(text_surface); // 移除原来的SDL_DestroyTexture(ctx->text_texture); 这行代码 }
- 修改
get_font_texture函数,删除提前关闭字体和退出TTF的代码,新增字体加载失败判断:
int get_font_texture(struct Context *ctx) { ctx->font = TTF_OpenFont("assets/fonts/Alef-Regular.ttf", 30); if (!ctx->font) { printf("打开字体失败: %s\n", TTF_GetError()); return 0; } set_font_text(ctx, "NEIL DU TOIT"); // 移除 TTF_CloseFont(ctx->font); 和 TTF_Quit(); 这两行代码 return 1; }
- 修改编译命令,添加
--preload-file参数将assets目录打包到虚拟文件系统:
emcc main.c -s USE_SDL=2 -s WASM=1 -s USE_SDL_TTF=2 -O3 --preload-file assets/ -o main.js
额外说明
emscripten_set_main_loop 执行后不会返回,main函数中主循环之后的资源释放代码永远不会执行,如果需要释放资源可以通过atexit注册退出回调实现。
内容的提问来源于stack exchange,提问作者Neil
相关产品推荐
相关产品推荐

