You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 18:35:24