x64 Windows下memcpy写入av_malloc内存致av_free崩溃问题排查
问题分析与解决方案
核心原因:双重内存释放
你的程序崩溃和memcpy、内存对齐无关,是重复释放同一块内存导致的。avio_alloc_context会接管你传入的buffer内存所有权,当调用avformat_close_input时,FFmpeg内部会自动销毁AVIOContext并释放其关联的buffer。你后续手动调用av_free(buffer),就触发了双重释放,直接导致程序崩溃。
修复步骤
- 移除所有手动调用的
av_free(buffer),让FFmpeg负责buffer的释放。 - 确保
std::vector<uint8_t> data的生命周期覆盖FFmpeg读取数据的全过程(你的代码里这部分是正确的,data在main函数内,直到程序结束才会销毁)。
修复后的完整代码
#include<iostream> #include<memory> #include<vector> extern "C" { #include <libavcodec/avcodec.h> #include<libavformat/avformat.h> #include <libavutil/imgutils.h> #include<libswscale/swscale.h> #include<libswresample/swresample.h> } struct BufferData { uint8_t* ptr; size_t size; size_t file_size; }; int main() { auto file=fopen("E:/test.jpg", "rb"); fseek(file, 0, SEEK_END); auto fileSize = ftell(file); fseek(file, 0, SEEK_SET); auto data = std::vector<uint8_t>(fileSize); fread(data.data(), sizeof(uint8_t), fileSize, file); fclose(file); auto test = BufferData(); test.ptr = data.data(); test.size = data.size(); test.file_size = data.size(); auto buffer = (uint8_t*)av_malloc(4096 * 10); char errStr[128] = { 0 }; auto avformatContext = avformat_alloc_context(); auto avioContext = avio_alloc_context(buffer, 4096, 0, &test, [](void* opaque, uint8_t* buf, int buf_size) { BufferData* bd = (BufferData*)opaque; auto size = std::min(bd->size, (size_t)buf_size); if (!size) { return -1; } memcpy(buf, bd->ptr, size); bd->ptr += size; bd->size -= size; return (int)size; }, NULL, NULL); avformatContext->pb = avioContext; avformatContext->flags = AVFMT_FLAG_CUSTOM_IO; auto ret = avformat_open_input(&avformatContext, nullptr, nullptr, nullptr); if (ret != 0) { av_strerror(ret, errStr, sizeof(errStr)); std::cout << errStr << std::endl; avformat_close_input(&avformatContext); return 0; } ret = avformat_find_stream_info(avformatContext, nullptr); if (ret < 0) { av_strerror(ret, errStr, sizeof(errStr)); std::cout << errStr << std::endl; avformat_close_input(&avformatContext); return 0; } av_dump_format(avformatContext, 0, nullptr, 0); auto videoIndex = av_find_best_stream(avformatContext, AVMEDIA_TYPE_VIDEO, -1, -1, nullptr, 0); if (videoIndex == AVERROR_STREAM_NOT_FOUND) { avformat_close_input(&avformatContext); return 0; } else if (videoIndex == AVERROR_DECODER_NOT_FOUND) { avformat_close_input(&avformatContext); return 0; } auto videoCodecPar = avformatContext->streams[videoIndex]->codecpar; auto videoCodec = avcodec_find_decoder(videoCodecPar->codec_id); if (!videoCodec) { avformat_close_input(&avformatContext); return 0; } avformat_close_input(&avformatContext); }
额外说明
- 如果需要手动管理buffer内存,可以在调用
avio_alloc_context时,将buffer参数设为NULL,然后通过自定义的read_packet回调自行处理内存,但这种场景下你当前的逻辑不需要这么做。 - 测试时确保
E:/test.jpg路径存在,避免因文件读取失败导致的其他问题。
内容的提问来源于stack exchange,提问作者PeacefulWindy
相关产品推荐
相关产品推荐

