none
ISpVoice内存暴涨的问题 RRS feed

  • 问题

  • bool CMineCASDlg::wavmake(CString str)
    {
    ISpVoice * pVoice= NULL;
    if (FAILED(::CoInitialize(NULL)))
    return false;

    HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL,
    IID_ISpVoice, (void **)&pVoice);
    if( SUCCEEDED( hr ) )
    {
    CComPtr<ISpStream> cpWavStream;
    CComPtr<ISpStreamFormat> cpOldStream;
    CSpStreamFormat OriginalFmt;
    pVoice->GetOutputStream(&cpOldStream);
    OriginalFmt.AssignFormat(cpOldStream);
    hr = SPBindToFile( L"output.wav",SPFM_CREATE_ALWAYS,
    &cpWavStream,&OriginalFmt.FormatId(),
    OriginalFmt.WaveFormatExPtr() );
    if( SUCCEEDED( hr ) )
    {
    pVoice->SetOutput(cpWavStream,TRUE);
    pVoice->Speak(str.AllocSysString(),0,NULL); 


    }
    cpWavStream.Release();
    pVoice->SetOutput(NULL,FALSE);
            cpOldStream.Release();
    pVoice->Release();
    pVoice = NULL;


    }


    ::CoUninitialize();

    return true;
    }


    if (FAILED(::CoInitialize(NULL)))
    return false;

    只要执行这句就会造成内存暴涨,下面释放了,但是不管用,请问,有什么办法是内存不暴涨,谢谢

    2013年1月23日 9:13

答案

  • 不好意思啊,经过测试

    if (FAILED(::CoInitialize(NULL)))
                    return false;

    这个话造成的内存暴涨,请问,怎么办,谢谢

    对不起,我代码改成这样后,仍然没有你提到的问题:

    int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow)
    {
    	for(int j =0;j < 100;j++)
    	{
    		HRESULT hRes = ::CoInitialize(NULL);
    
    		ISpVoice * pVoice= NULL;
    		HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL,IID_ISpVoice, (void **)&pVoice);
    
    		for(int i =0;i<100;i++)
    		{
    			CComPtr<ISpStreamFormat> cpOldStream;
    			hr = pVoice->GetOutputStream(&cpOldStream);
    			cpOldStream.Release();
    		}
    
    		pVoice->Release();
    		pVoice = NULL;
    
    		::CoUninitialize();
    	}
    	return 0;
    }

    可能你测试的代码还包含另外的部分,请你在你其它代码中查找原因。
    按照最佳做法,::CoInitialize 只应该在启动时执行一次。
    2013年1月23日 9:28

全部回复

  • bool CMineCASDlg::wavmake(CString str)
    {
            ISpVoice * pVoice= NULL;
            if (FAILED(::CoInitialize(NULL)))
                    return false;

            HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL,
                    IID_ISpVoice, (void **)&pVoice);
            if( SUCCEEDED( hr ) )
            {
                    CComPtr<ISpStream> cpWavStream;
                    CComPtr<ISpStreamFormat> cpOldStream;
                    CSpStreamFormat OriginalFmt;
                    pVoice->GetOutputStream(&cpOldStream);
                    OriginalFmt.AssignFormat(cpOldStream);
                    hr = SPBindToFile( L"output.wav",SPFM_CREATE_ALWAYS,
                            &cpWavStream,&OriginalFmt.FormatId(),
                            OriginalFmt.WaveFormatExPtr() );
                    if( SUCCEEDED( hr ) )
                    {
                            pVoice->SetOutput(cpWavStream,TRUE);
                            pVoice->Speak(str.AllocSysString(),0,NULL);
                           
                           
                    }
                    cpWavStream.Release();
                    pVoice->SetOutput(NULL,FALSE);
            cpOldStream.Release();
                    pVoice->Release();
                    pVoice = NULL;
                   
           
                    }
           
           
            ::CoUninitialize();

            return true;
    }


    pVoice->GetOutputStream(&cpOldStream);只要执行这句就会造成内存暴涨,下面释放了,但是不管用,请问,有什么办法是内存不暴涨,谢谢    
    2013年1月23日 5:54
  • 暴涨了多少?

    2013年1月23日 6:15
  • 每运行1次上涨14000k
    • 已编辑 creamnn 2013年1月23日 6:29
    2013年1月23日 6:17
  • 每运行1次上涨1400k

    对所有 CComPtr<T> 都显式释放一次,例如:cpOldStream.Release();
    2013年1月23日 6:28
  • 大哥,你看到我释放了把
    2013年1月23日 6:36
  • 大哥,你看到我释放了把

    现在看到了。你把代码精简下,只到 GetOutputStream 为止,类似:

    for(int i = 0 ;i < 1000;i++)

    {

        HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL,IID_ISpVoice, (void **)&pVoice);

    pVoice->GetOutputStream(&cpOldStream);

    pVoice->Release();

     }

    看看你的内存是如何增长的。

    2013年1月23日 6:43
  • 大哥放循环里面会出错
    2013年1月23日 7:00
  • 我就是调用一次这个函数,生成的.exe文件的进程占用的内存就增加14000k
    2013年1月23日 7:02
  • 大哥放循环里面会出错

    为什么会出错?怎么会出错呢?

    难道还限制了一个进程只能 CoCreateInstance 一次 CLSID_SpVoice 实例?

    • 已编辑 Skyseer 2013年1月23日 7:18
    2013年1月23日 7:17
  • 我就是调用一次这个函数,生成的.exe文件的进程占用的内存就增加14000k

    增加 14 MB,或许是一个正常值呢?只要它不是总是增加就行。

    2013年1月23日 7:21
  • pVoice->GetOutputStream(&cpOldStream);
            OriginalFmt.AssignFormat(cpOldStream);

    我就把这2句放到循环里就出现运行时异常

    2013年1月23日 7:22
  • expression p==0
    2013年1月23日 7:24
  • pVoice->GetOutputStream(&cpOldStream);
            OriginalFmt.AssignFormat(cpOldStream);

    我就把这2句放到循环里就出现运行时异常

    你的代码是这样的吗:

    for(int i = 0 ;i < 1000;i++)

    {

     ISpVoice * pVoice= NULL;

    CComPtr<ISpStreamFormat> cpOldStream;

        HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL,IID_ISpVoice, (void **)&pVoice);

    pVoice->GetOutputStream(&cpOldStream);

    pVoice->Release();

    }


    • 已编辑 Skyseer 2013年1月23日 7:27
    2013年1月23日 7:26
  • 不调用这一句

    OriginalFmt.AssignFormat(cpOldStream);

    会报出现冲突,还有

    每调用一次这个函数都会增加14m,那我要做很多个wav文件不就崩溃了

    2013年1月23日 7:29
  • 不调用这一句

    OriginalFmt.AssignFormat(cpOldStream);

    会报出现冲突,还有

    每调用一次这个函数都会增加14m,那我要做很多个wav文件不就崩溃了


    或许你应该只实例化一次  ISpVoice ,然后重复使用。我没有实际用过的,所以我只能建议你多做测试来找到正确的使用方式,建议你思路放开阔点,多琢磨代码并测试。莫非我得去下载一个SDK,帮你调试?

    • 已编辑 Skyseer 2013年1月23日 7:43
    2013年1月23日 7:42
  • 你不懂回答什么啊
    2013年1月23日 7:52
  • 你不懂回答什么啊

    因为别人没提到过这个问题,而且也没有报告说有此BUG,那么推断应该是你的使用方式不正确,或者因为别的原因,造成了内存无限增长。

    我回答的目的是介绍一些如何调查此类问题的方式,那么空闲的时候我也会下载一个SDK来测试下,首先要确认的是你观察到的现象是不是特例。

    而且,好像也没有别的人来回答你的问题了,所以多一个人讨论,就会帮助你打开思路。
    • 已编辑 Skyseer 2013年1月23日 8:02
    2013年1月23日 8:01
  • 没报告不代表没有,可能是没有多少人用这个,我把其他代码都屏蔽了,只是调用那2句,而且只初始化1次,就会发生内存暴涨,这跟调用错误没什么关系把,不过,还是谢谢你
    2013年1月23日 8:07
  • 没报告不代表没有,可能是没有多少人用这个,我把其他代码都屏蔽了,只是调用那2句,而且只初始化1次,就会发生内存暴涨,这跟调用错误没什么关系把,不过,还是谢谢你

    我测试了下,这是我的代码:

    int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow)
    {
    	HRESULT hRes = ::CoInitialize(NULL);
    
    	ISpVoice * pVoice= NULL;
    	HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL,IID_ISpVoice, (void **)&pVoice);
    
    	for(int i =0;i<100;i++)
    	{
    		CComPtr<ISpStreamFormat> cpOldStream;
    		hr = pVoice->GetOutputStream(&cpOldStream);
    		cpOldStream.Release();
    	}
    
    	pVoice->Release();
    	pVoice = NULL;
    
    	::CoUninitialize();
    	return 0;
    }

    根据统计:

    程序启动后,内存:1344K;

    调用CoCreateInstance后,内存:1752K;

    调用一次 GetOutputStream 后,内存:9196K;

    调用 cpOldStream.Release() 不释放内存,仍然为 9196K;

    循环100次,内存大小不变;

    退出循环后,调用 pVoice->Release() 后,内存:2356K;

    从调试结果来看,GetOutputStream 的确会造成内存“暴涨”(大约7.5MB),但是多次调用并不会重复增长。

    因此如果你按照我写的代码来测试,现象仍然像你描述的这样的话,那么很有可能是你系统的某个声卡驱动资源泄露了。

    2013年1月23日 8:33
  • 不好意思啊,经过测试

    if (FAILED(::CoInitialize(NULL)))
                    return false;

    这个话造成的内存暴涨,请问,怎么办,谢谢

    2013年1月23日 9:12
  • bool CMineCASDlg::wavmake(CString str)
    {
        ISpVoice * pVoice= NULL;
        if (FAILED(::CoInitialize(NULL)))
            return false;

        HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL,
            IID_ISpVoice, (void **)&pVoice);
        if( SUCCEEDED( hr ) )
        {
            CComPtr<ISpStream> cpWavStream;
            CComPtr<ISpStreamFormat> cpOldStream;
            CSpStreamFormat OriginalFmt;

            pVoice->GetOutputStream(&cpOldStream);
            OriginalFmt.AssignFormat(cpOldStream);

            hr = SPBindToFile( L"output.wav",SPFM_CREATE_ALWAYS,
                &cpWavStream,&OriginalFmt.FormatId(),
                OriginalFmt.WaveFormatExPtr() );
            if( SUCCEEDED( hr ) )
            {
                pVoice->SetOutput(cpWavStream,TRUE);


                pVoice->Speak(str.AllocSysString(),0,NULL);


            }
            cpWavStream.Release();
            pVoice->SetOutput(cpOldStream,FALSE);
            cpOldStream.Release();
            pVoice->Speak(NULL,SPF_PURGEBEFORESPEAK,NULL);
            pVoice->Release();

            pVoice = NULL;


            }


        ::CoUninitialize();

        return true;
    }

     if (FAILED(::CoInitialize(NULL)))
            return false;

        HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL,
            IID_ISpVoice, (void **)&pVoice);
        if( SUCCEEDED( hr ) )
        {
            CComPtr<ISpStream> cpWavStream;
            CComPtr<ISpStreamFormat> cpOldStream;
            CSpStreamFormat OriginalFmt;
            
            pVoice->GetOutputStream(&cpOldStream);
            OriginalFmt.AssignFormat(cpOldStream);

    }

    一执行这段代码就会造成内存暴涨,每执行一次,进程就会增长14m,请问,怎么解决,谢谢

                                                                                        
    2013年1月23日 9:27
  • 不好意思啊,经过测试

    if (FAILED(::CoInitialize(NULL)))
                    return false;

    这个话造成的内存暴涨,请问,怎么办,谢谢

    对不起,我代码改成这样后,仍然没有你提到的问题:

    int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow)
    {
    	for(int j =0;j < 100;j++)
    	{
    		HRESULT hRes = ::CoInitialize(NULL);
    
    		ISpVoice * pVoice= NULL;
    		HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL,IID_ISpVoice, (void **)&pVoice);
    
    		for(int i =0;i<100;i++)
    		{
    			CComPtr<ISpStreamFormat> cpOldStream;
    			hr = pVoice->GetOutputStream(&cpOldStream);
    			cpOldStream.Release();
    		}
    
    		pVoice->Release();
    		pVoice = NULL;
    
    		::CoUninitialize();
    	}
    	return 0;
    }

    可能你测试的代码还包含另外的部分,请你在你其它代码中查找原因。
    按照最佳做法,::CoInitialize 只应该在启动时执行一次。
    2013年1月23日 9:28
  • 你好,
    我把该回复标记为了答案。
    如果您有什么不同意的地方请取消标记。
    此致

    Elegentin Xie
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2013年2月5日 11:32
    版主