养成好的编码习惯----由一个bug想到的

最近在做PCM音频合成项目,其中遇到了一个bug,花了大半天才解决,当然修改却很小,是一个很细节的问题。不过回想一下,之前也有类似的经历,觉得有点什么规律,写出来用以自勉,也许各位programmer也曾遇到过吧!:)

       下面是部分摘录的代码(颜色visual assist生成的)

/**/

 

HRESULT CALMInputPin::Convert(IMediaSample *pIn, IMediaSample *pOut)

 

{

 

       HRESULT hr = S_OK;

 

       /* get suggested size of destination buffer */

 

       long len = pIn->GetActualDataLength();

 

       DWORD suggested_dest_size = 0;

 

       hr = acmStreamSize(m_hStream, len, &suggested_dest_size, ACM_STREAMSIZEF_DESTINATION);

 

       if (hr != MMSYSERR_NOERROR)

 

              return hr;

 

 

       ACMSTREAMHEADER acmhdr;

 

 

       acmhdr.cbStruct = sizeof(acmhdr);

 

       hr = pIn->GetPointer(&acmhdr.pbSrc);

 

       hr = pOut->GetPointer(&acmhdr.pbDst);

 

       acmhdr.cbSrcLength = pIn->GetActualDataLength();

 

       acmhdr.cbDstLength = suggested_dest_size;

 

       acmhdr.dwSrcUser = (DWORD)pIn;

 

       acmhdr.dwDstUser = (DWORD)pOut;

 

       acmhdr.dwUser = (DWORD)this;

 

       acmhdr.fdwStatus = 0L;

 

 

       // ???这里总是返回 error code 10

 

       hr = acmStreamPrepareHeader(m_hStream, &acmhdr, 0);

 

       if (hr != MMSYSERR_NOERROR)

 

              return hr;

 

 

       /* send buffer to compressor/uncompressor (ACM) */

 

       hr = acmStreamConvert (m_hStream, &acmhdr, ACM_STREAMCONVERTF_BLOCKALIGN);

 

       if (hr != MMSYSERR_NOERROR )

 

       {

 

              return hr;

 

       }

 

 

       hr = acmStreamUnprepareHeader(m_hStream, &acmhdr, 0);

 

       if (hr != MMSYSERR_NOERROR)

 

              return hr;

 

      

 

    REFERENCE_TIME rtStart, rtEnd;

 

 

       len = pIn->GetActualDataLength();

 

       pIn->GetTime(&rtStart, &rtEnd);

 

       rtEnd = rtStart + len;

 

       pOut->SetTime(&rtStart, &rtEnd);

 

 

       pOut->SetActualDataLength(acmhdr.cbDstLength);

 

      

 

    return S_OK;

 

}

 

//

 

 

这里涉及到DirectShowACM的结构和函数,不过思路还比较清晰。细心的话可以看出这些代码,是“拼凑”出来的(提高开发速度嘛!),分别来自是网上的开源项目和DirectShow附带的源文件。从逻辑上说也没有什么问题,当然调试发现总是有一个错误。

唯一的线索是error code 10Error Lookup解释为“环境错误”,这能说明什么问题呢?当然笔者对ACM也不是很了解,于是花了几个小时看了文档,了解了一些背景知识,但没有什么发现什么有价值的东西。又参考了其它项目的代码,不过别人使用的c++模板语法,而且要拆解出关键的代码需要很多时间,所以搞来搞去也没有思路。

思路在哪里?在经过了一些其它的尝试的时候,觉得还是不行。最后又去调试别人的代码,可以运行通过。有一点是可以肯定的,程序的流程没有问题,可能是其中遗漏了某些细节。对比两段代码后发现,ACMSTREAMHEADER的某些成员变量没有初始化。难道真是这个问题吗?于是在结构体变量申明后面添加了

 

memset (&acmhdr, 0, sizeof(acmhdr));

 

这样所有的成员先初始化为0。在调试,问题解决了!后来在MSDN里面发现了ACMAPP Sample工程,里面有这么一段代码:

 

   

 

pash->cbStruct          = sizeof(*pash);

 

    pash->fdwStatus         = 0L;

 

    pash->dwUser            = 0L;

 

    pash->pbSrc             = paacd->pbSrc;

 

    pash->cbSrcLength       = paacd->cbSrcReadSize;

 

    pash->cbSrcLengthUsed   = 0L;

 

    pash->dwSrcUser         = paacd->cbSrcReadSize;

 

    pash->pbDst             = paacd->pbDst;

 

    pash->cbDstLength       = paacd->cbDstBufSize;

 

    pash->cbDstLengthUsed   = 0L;

 

pash->dwDstUser         = paacd->cbDstBufSize;

 

 

这个结构体的定义如下:

typedef struct tACMSTREAMHEADER

 

{

 

    DWORD           cbStruct;               // sizeof(ACMSTREAMHEADER)

 

    DWORD           fdwStatus;              // ACMSTREAMHEADER_STATUSF_*

 

    DWORD           dwUser;                 // user instance data for hdr

 

    LPBYTE          pbSrc;

 

    DWORD           cbSrcLength;

 

    DWORD           cbSrcLengthUsed;

 

    DWORD           dwSrcUser;              // user instance data for src

 

    LPBYTE          pbDst;

 

    DWORD           cbDstLength;

 

    DWORD           cbDstLengthUsed;

 

    DWORD           dwDstUser;              // user instance data for dst

 

    DWORD           dwReservedDriver[10];   // driver reserved work space

 

 

} ACMSTREAMHEADER, *PACMSTREAMHEADER, FAR *LPACMSTREAMHEADER;

 

11个成员虽然没有全部清零,但是除了dwReservedDriver[10]都赋了值。

 

总结:这类错误是由于某些结构体成员没有正确的赋值而造成的,在Debug模式中没有赋值的变量一般初始化为0xcc,在Release模式中一般是0x00,都是按字节序。所以编译器为了做了赋值,但是这些值是错误的,所以在编码的过程中必须处理这个细节。要么先全部初始化为0,要么对所有相关的变量都赋值。

 

       笔者写程序也有3年了,但是仍然犯这个错误,虽然是在追的比较急的时候。所以必须在平时养成良好的习惯,同时克服外部的压力,写出高质量的代码;而不是风风火火赶代码,最后还得花很多时间去找错,得不偿失!这就是笔者要与大家共勉的啊!

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值