明智而审慎的使用形参

来源:互联网 发布:网络黑彩公司怎么举报 编辑:程序博客网 时间:2024/06/09 16:35

问题:

wince6.0,程序运行会出现崩溃。在程序运行的时候Total memory:66420KB, Current usage:26136KB,可见还有很多空间可以用。

我自己用标准c++写的一个模块Comtrade,现在要加到wince mfc的工程中,mfc程序会每次会new 大约15k的空间如:

CComTradeData *comtradeData =new CComTradeData[1024];

然后会读取文件中得数据至此空间中:
comtrade.ReadData(comtradeData);


然后保存comtrade数据至波形数据缓冲区
for(int i =0;i<sampNum;i++){    for (int j=0;j<3;j++)    {        m_comtradeWaveData.volWaveData[j][i] =(comtradeData[i].getAnalogChannelData()[j])*a+b;        m_comtradeWaveData.curWaveData[j][i] =(comtradeData[i].getStatusChannelData()[j])*a+b;    }}

之后会delete[] comtradeData


程序代码如下:

void COverAlamDlg::ReadComtradeData( CComTrade comtrade ){    //123321方式清空波形数据缓冲区    for (int i=2;i>=0;i--)    {        if (m_comtradeWaveData.curWaveData[i] != NULL)        {            delete[] m_comtradeWaveData.curWaveData[i];            m_comtradeWaveData.curWaveData[i] =NULL;        }        if (m_comtradeWaveData.volWaveData[i] !=NULL )        {            delete[] m_comtradeWaveData.volWaveData[i];            m_comtradeWaveData.volWaveData[i] =NULL;        }    }    ...    //采样数    int sampNum =comtrade.getRatesList()->HeadSampRate()->getEndSample();    CComTradeData *comtradeData =new CComTradeData[sampNum];    //读取数据至comtradeData缓冲区    comtrade.ReadData(comtradeData);    //申请空间    for (int i =0; i<3; i++)    {        if (m_comtradeWaveData.volWaveData[i] == NULL)        {            m_comtradeWaveData.volWaveData[i] =new float[sampNum];        }        if (m_comtradeWaveData.curWaveData[i] == NULL)        {            m_comtradeWaveData.curWaveData[i] =new float[sampNum];        }    }    //保存comtrade数据至波形数据缓冲区    for(int i =0;i<sampNum;i++)    {        for (int j=0;j<3;j++)        {            m_comtradeWaveData.volWaveData[j][i] =(comtradeData[i].getAnalogChannelData()[j])*a+b;            m_comtradeWaveData.curWaveData[j][i] =(comtradeData[i].getStatusChannelData()[j])*a+b;        }    }      delete[] comtradeData;}



说明:
1.m_comtradeWaveData中的数据会交给绘制波形的模块绘制,整个过程如下:
C**Dlg::OnNMDblclkDetailList(***)
{
....
CComtrade ctdReadData;
....
ReadComtradeData(ctdReadData);  
//传递波形数据至回显页面,绘制波形
m_showTstRecordDlg.DrawTstRecord(&m_comtradeWaveData);
m_showTstRecordDlg.ShowWindow(SW_SHOW);
....
}


2.当多次调用OnNMDblclkDetailList时就会崩溃,整个系统都瘫痪。用串口工具查看到了发生崩溃的地址,然后
跟踪地址,发现是系统afxtempl.h中Line1638行 CMap<void *,void *,void *,void *>::GetAssocAt出现的异常。
有时候跟踪地址,发现异常会出现在xutility中,std::_Container_base_secure::_Orphan_all()Line225.


3.运气好的话执行OnNMDblclkDetailList十来次都不会有任何问题,但是大量执行该函数总会出问题。


4.将m_showTstRecordDlg.DrawTstRecord(&m_comtradeWaveData)和
    m_showTstRecordDlg.ShowWindow(SW_SHOW)注释掉。

  只让其执行ReadComtradeData函数却什么异常也不会出现。


问题解决:

函数参数改为引用即可解决!!!如此小小一个引用竟还得我多日不眠!!

void COverAlamDlg::ReadComtradeData( CComTrade &comtrade )

引发的思考:

那时候为了懒省事,就直接将函数形参搞成变量形式,心里想着,又不会修改comtrade对象的值,只会调用它的值而已。这样做的开销实际上是非常大的,

因为系统会为comtrade重新拷贝一段内存,而comtrade里面有一段内存是动态申请的,所以系统经过一系列麻烦的过程(我也不清楚)之后运行完此函数

就会调用comtrade的析构函数,也许一次两次不会出问题,但是次数多了,系统,也许就会将这个析构函数和传递参数之前的那个对象就有可能重复释放

相同的空间,导致系统崩溃!

可见,系统崩溃了,幸好,我内心的强大,自身没有崩溃,终究解决这个问题。得出的经验是,如果遇到形参,其仅仅是一个int、float等这样的数据结构

时不打紧,尽管用局部变量的形式,如果遇到形参是个非常大的、内部结构异常复杂的类或结构体时,请慎重。最好使用引用或者是指针的const指针形式,

避免莫名其妙的错误。



	
				
		
原创粉丝点击