调用IMG_Load_RW()处理二进制stringstream时触发访问冲突问题
问题分析与修复方案
代码中的核心错误
- 未定义变量:
ss_do和p_sdlrwops_i是未声明的变量,需分别替换为ss_image_data和p_sdlrwops_image。 - SDL_RWops初始化错误:
SDL_RWFromMem需要传入二进制数据的缓冲区指针,而非stringstream对象的地址。你应该从stringstream导出的字符串中获取数据指针。 - 二进制读写逻辑错误:使用
>>和<<进行二进制字节的读写会触发格式化处理,导致二进制数据(如空字符、控制字符)被篡改或丢失,必须用read()和write()方法处理原始字节。 - 临时对象生命周期问题:直接调用
ss_image_data.str().c_str()会生成临时字符串,其指针在语句结束后会失效,需先将数据保存到局部字符串变量中。
修正后的代码
bool b_get_SDLSurface_from_stream(string str_path, SDL_Surface** sdls_image) { ifstream ifstr_i(str_path.c_str(), std::ios_base::binary); if (!ifstr_i.is_open()) { return false; } stringstream ss_image_data(stringstream::out | stringstream::binary); unsigned char uint8_b; // 用read()读取单个字节,避免格式化问题 while (ifstr_i.read(reinterpret_cast<char*>(&uint8_b), 1)) { uint8_b -= 3; // 用write()写入解密后的字节,保证二进制正确性 ss_image_data.write(reinterpret_cast<char*>(&uint8_b), 1); } // 检查是否读取到有效数据 if (ss_image_data.str().empty()) { ifstr_i.close(); return false; } // 保存字符串避免临时对象失效 string img_data = ss_image_data.str(); SDL_RWops* p_sdlrwops_image = SDL_RWFromMem(const_cast<char*>(img_data.c_str()), img_data.size()); if (!p_sdlrwops_image) { ifstr_i.close(); return false; } *sdls_image = IMG_Load_RW(p_sdlrwops_image, 0); if (!*sdls_image) { SDL_FreeRW(p_sdlrwops_image); ifstr_i.close(); return false; } SDL_FreeRW(p_sdlrwops_image); ifstr_i.close(); return true; }
额外说明
- 调用
SDL_FreeRW手动释放RWops资源,避免内存泄漏(IMG_Load_RW第二个参数传0表示不自动释放该资源)。 - 用
ifstream构造函数直接打开文件,简化代码逻辑。 - 用
img_data.empty()代替rdbuf()->in_avail(),更直观检查是否有有效数据。
内容的提问来源于stack exchange,提问作者kyluck
相关产品推荐
相关产品推荐

