C DirectShow中Access violation reading location错误求助
DirectShow C代码出现Access Violation错误排查
在Visual Studio中运行基于DirectShow的C语言代码时,持续出现Access violation reading location错误,且无法正常打印文件路径排查问题。朋友认为是硬件故障,但我无法确定。
原代码
#include <dshow.h> #include <stdio.h> #include <Windows.h> void main(void) { while (TRUE) { char SongName[10]; printf("Song name:\n"); scanf_s("%s", &SongName,10); HRESULT hr = CoInitialize(NULL); IGraphBuilder* pGraph = NULL; hr = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, &IID_IGraphBuilder, (void**)&pGraph); IMediaControl* pControl = NULL; IMediaEvent* pEvent = NULL; hr = pGraph->lpVtbl->QueryInterface(pGraph, &IID_IMediaControl, (void**)&pControl); hr = pGraph->lpVtbl->QueryInterface(pGraph, &IID_IMediaEvent, (void**)&pEvent); char SongAddress = (L"C:/Users/Desktop/AudioPlayer/%s",SongName); wprintf("%s", SongAddress); hr = pGraph->lpVtbl->RenderFile(pGraph,SongAddress, NULL); hr = pControl->lpVtbl->Run(pControl); FILTER_STATE fs; hr = pControl->lpVtbl->GetState(pControl,10000, (OAFilterState*)&fs); if (fs != NULL) { printf("%d", fs); } long evCode = 0; pEvent->lpVtbl->WaitForCompletion(pEvent, INFINITE, &evCode); pControl->lpVtbl->Release(pControl); pEvent->lpVtbl->Release(pEvent); pGraph->lpVtbl->Release(pGraph); CoUninitialize(); } }
错误发生在这一行:
hr = pGraph->lpVtbl->RenderFile(pGraph,SongAddress, NULL);
问题根源及修复方案
1. 字符串处理错误(核心问题)
- 原代码中
char SongAddress = (L"C:/Users/Desktop/AudioPlayer/%s",SongName);完全错误:- 逗号表达式仅返回最后一个值
SongName,且将字符数组赋值给单个char变量,类型不匹配导致内存乱码。 RenderFile要求传入宽字符字符串(LPCWSTR),需要把窄字符的文件名拼接成宽字符路径。
- 逗号表达式仅返回最后一个值
wprintf("%s", SongAddress);格式符错误,宽字符应该用%ls,且变量类型错误导致无法打印。
2. 缺失COM调用错误检查
CoCreateInstance调用后未检查返回值,如果创建FilterGraph失败,pGraph为NULL,后续调用接口会直接崩溃。scanf_s("%s", &SongName,10);中SongName是数组名,不需要加&,应改为scanf_s("%s", SongName, sizeof(SongName));。
3. COM库重复初始化
CoInitialize和CoUninitialize放在循环内,每次循环都初始化/销毁COM库,不符合规范,应移到循环外。
修复后的代码
#include <dshow.h> #include <stdio.h> #include <Windows.h> #include <stdlib.h> void main(void) { // 初始化COM库,放在循环外 HRESULT hr = CoInitialize(NULL); if (FAILED(hr)) { printf("COM初始化失败: 0x%X\n", hr); return; } while (TRUE) { char SongName[10]; printf("请输入歌曲名(不含后缀,长度≤9):\n"); // 修正scanf_s参数 scanf_s("%s", SongName, sizeof(SongName)); IGraphBuilder* pGraph = NULL; hr = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, &IID_IGraphBuilder, (void**)&pGraph); if (FAILED(hr) || pGraph == NULL) { printf("创建FilterGraph失败: 0x%X\n", hr); continue; } IMediaControl* pControl = NULL; IMediaEvent* pEvent = NULL; hr = pGraph->lpVtbl->QueryInterface(pGraph, &IID_IMediaControl, (void**)&pControl); if (FAILED(hr)) { printf("获取IMediaControl失败: 0x%X\n", hr); pGraph->lpVtbl->Release(pGraph); continue; } hr = pGraph->lpVtbl->QueryInterface(pGraph, &IID_IMediaEvent, (void**)&pEvent); if (FAILED(hr)) { printf("获取IMediaEvent失败: 0x%X\n", hr); pControl->lpVtbl->Release(pControl); pGraph->lpVtbl->Release(pGraph); continue; } // 拼接宽字符路径 wchar_t SongAddress[MAX_PATH] = {0}; swprintf_s(SongAddress, MAX_PATH, L"C:/Users/Desktop/AudioPlayer/%s.wav", SongName); // 正确打印宽字符 wprintf(L"歌曲路径: %ls\n", SongAddress); hr = pGraph->lpVtbl->RenderFile(pGraph, SongAddress, NULL); if (FAILED(hr)) { printf("RenderFile失败: 0x%X\n", hr); pEvent->lpVtbl->Release(pEvent); pControl->lpVtbl->Release(pControl); pGraph->lpVtbl->Release(pGraph); continue; } hr = pControl->lpVtbl->Run(pControl); if (FAILED(hr)) { printf("播放失败: 0x%X\n", hr); pEvent->lpVtbl->Release(pEvent); pControl->lpVtbl->Release(pControl); pGraph->lpVtbl->Release(pGraph); continue; } FILTER_STATE fs; hr = pControl->lpVtbl->GetState(pControl, 10000, (OAFilterState*)&fs); if (SUCCEEDED(hr)) { printf("当前播放状态: %d\n", fs); } long evCode = 0; pEvent->lpVtbl->WaitForCompletion(pEvent, INFINITE, &evCode); // 释放资源 pControl->lpVtbl->Release(pControl); pEvent->lpVtbl->Release(pEvent); pGraph->lpVtbl->Release(pGraph); } // 销毁COM库,放在循环结束后 CoUninitialize(); }
内容的提问来源于stack exchange,提问作者AerospaceMilitary420
相关产品推荐
相关产品推荐

