Telechips平臺的WinCE下的wave驅動報錯的原因

最近公司有個項目使用的百度Carlife語音識別出現wavedev.dll報錯問題。根據經驗,這種報錯問題,一般都是指針越界或者stack over flow等錯誤。
於是根據wavedev.map文件定位到了midiNote.cpp的函數NoteOn中的數組PitchTable。可仔細分析這個函數以及這個數組,認爲怎麼都不可能導致內存越

界錯誤——PitchTable[ Note % 12 ],Note的值怎麼都不可能使得引用這個數組時越界。map文件的定位錯誤的方法有時——尤其是底層驅動層涉及到

硬件上下文的庫中,不管用!
爲了正確定位出報錯的位置,另闢思路,從應用層調用waveOutOpen、waveOutWrite函數開始,加入打印語句,一直追蹤這兩個API函數的調用過程,看

看哪個打印語句沒有打印出來,報錯的位置就很有可能出現在這個函數中!爲了調查這個問題,也同時將wave驅動的框架弄明白了——我有篇文章大致

介紹了waveOutOpen、waveOutWrite的調用過程。從這個過程中,可以看出PCM數據是如何從應用層流到驅動層的。
遵循着上面的思路,終於在函數OutputStreamContextNonPCM::Render2中定位到了異常:
1、wave驅動層的Render2函數在訪問用戶的PCM數據時,越界訪問!
2、這個函數聲明瞭太多的局部變量,導致stack over flow!
於是針對上面兩個錯誤,給出瞭如下兩個辦法:
1、在這個函數裏面訪問用戶數據之前,加入內存邊界檢查!例如:

if(m_WaveFormatEx.dwChannelMask & SPEAKER_FRONT_LEFT)
{
    if (pCurrData16>=pCurrDataEnd16)//added by zhujw for check PCM data buffer valid
    {
        goto Exit;
    }
    pCurrSamp0[0] = *pCurrData16;
    pCurrData16++;
}

2、將所有佔用內存較大的局部變量,全部改爲在heap中分配內存。

#if 1 //must use new heap memory .....comment by zhujw 20170630
    LONG *pCurrSamp0 = new LONG[MAXDADONUM];
    LONG *pCurrSamp1 = new LONG[MAXDADONUM];
    LONG *pPrevSamp0 = new LONG[MAXDADONUM];
    LONG *pPrevSamp1 = new LONG[MAXDADONUM];
    LONG *pOutSamp0 = new LONG[MAXDADONUM];
    LONG *pOutSamp1 = new LONG[MAXDADONUM];
#else//if use stack memory,it will be 'Data Abort'....comment by zhujw 20170630
    LONG CurrSamp0[MAXDADONUM];
    LONG CurrSamp1[MAXDADONUM];
    LONG PrevSamp0[MAXDADONUM];
    LONG PrevSamp1[MAXDADONUM];     
    LONG OutSamp0[MAXDADONUM];
    LONG OutSamp1[MAXDADONUM];
#endif

至此,經過測試,問題完美解決!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章