现在的位置: 首页 > 综合 > 正文

C++是十大错误

2013年03月28日 ⁄ 综合 ⁄ 共 3610字 ⁄ 字号 评论关闭

 

1.  数组下标访问越界

2.  使用野指针(指针未初始化就直接使用、delele完后继续使用、NEW申请不作NULL判断/托管后自己又手动DELETE)

3.  字符串结尾标志’\0’

4.  变量没有初始化

5.  变量名、枚举名、常量名字面意思、注释含义与使用时相反

6.  所有的可能抛异常的地方都要有try catch

7.  没有处理返回值

8.  函数局部变量或参数过大,堆栈溢出

9.  数据类型不一致,变量或参数赋值出错

10. 分支流程未释放动态申请的内存

代码案例:

1.   数组下标访问越界

Typedef TOCTET TEncodedSmsContent[MaxEncodedSmsContentLength + 1];//200

TEncodedSmsContent featureStr;         

 

#define MAX_MSG_LEN 255 //采用统一的扩展长度

char sMsgContent[MAX_MSG_LEN + 1]; 

memcpy(m_ismgAuthPriceReq.featureStr, pMessage->deliverReq->msgBody.getMsgContent(),

       pMessage->deliverReq->msgBody.getMsgLen());

2.   使用野指针

(1)使用未分配空间的指针、new操作不做null判断、delete后继续使用

CMessage* pMsg;

pMsg->decode(code);//未分配空间

-------------------------

CMessage* pMsg;

NEW(pMsg, CVACUserOrderServiceReq);

TCode code

pMsg->decode(code)

 

DELETE(pSession);

If(pSession-> isSessionOver())//未作null判断

{

    m_pSessionControl->removesession(pSession);

}

 

(2)指针托管后被误delete

NEW(pSession, CSubscribeSessionInfo);

CSessionProcessMgr::instance()->event(pSession->getSessionType(), pSession, code);

m_pSessionControl->addSession(pSession)

//上面event处理完了有可能会话已结束

if (pSession->isSessionOver())

{

    DELETE(pSession);//此时delete,那么托管的指针指向内存就被误释放了

    return;

}

3.   字符串结尾标志’\0’

typedef TOCTET RecordSequenceID[MaxVacSequenceIDLength];

RecordSequenceID VacSequenceID

sprintf(VacSequenceID, MaxVacSequenceIDLength, "%04d%02d%02d%02d%02d%02d%04d",

             (1900 + ts->tm_year),

             (1 + ts->tm_mon),

             ts->tm_mday,

             ts->tm_hour,

             ts->tm_min,

             ts->tm_sec,

             curSquenceId);

 

//缺少\0,后面在使用VacSequenceID就会出现内存越界访问

 

字符串结束符相关有许多安全函数可供调用:snprintf,strncpy,strncat,safecopy等等,不允许使用非安全函数

4.   变量没有初始化

class CMsgConvert_SMAPLike : public CMsgConvert

{

public:

    CMsgConvert_SMAPLike(){}

    virtual ~CMsgConvert_SMAPLike(){}

protected:   

    RecordNo m_recordNo;//变量没有初始化(所有变量都必须初始化)    

};

5.   变量名、枚举名、常量名字面意思、注释含义与使用时相反

CVACSubScirbeReq中字段:

CMsgFieldInt  m_isNeedNotifySP;  //CRM侧订购的是否需要通知SP

 

该字段本意是个枚举值(ENUM),取值有2个:

enum isNotifySP

{

    Notify_SP_NO = 1,      //不通知

    Notify_SP_YES    = 2   //通知SP

};

//下面的逻辑是需要通知sp才处理的,枚举含义和实际意义完全颠倒

if (From_CRM == pSessionInfo->m_reqInfo.m_CRMOrderFlag.asInt()

    && Notify_SP_NO == pSessionInfo->m_reqInfo.m_isNeedNotifySP.asInt())

6.   所有的可能抛异常的地方都要有try catch

const char *sql = "select msisdn, serviceid, spid, billmonth, amount, account, rewardAmount, rewardAccount,realaccount  from historyrecord where msisdn = :v1 and serviceid = :v2 and spid = :v3";

 

TINT nCommandIndex = m_pDbAgent->excute(sql, msisdn, pa, paCount);

if (nCommandIndex == Failed)

{

    return SearchResult_DBError;

}

CRecordSet rs;

rs.setSACommand(&CDBAgent::getInstance()->s_commandSet[nCommandIndex]);

//完全没有try和catch保护,一旦数据库出错就是一个core

7.   没有处理返回值

char* genMsgBuf(int iBufSize)

{

 char* pBuff = NULL;

 NEW_S(pBuff, char, iBufSize);

 return genMsgBuf;

}

//诸如此类内部动态分配内存并返回的函数,外部调用时一定要对返回值进行处理,否则就会出现内存泄露,一般来说哪里申请哪里释放,尽量避免内部申请外部释放的情况

8.   函数局部变量或参数过大,堆栈溢出

CCMMainCtrl_Impl cmMainctrl;//栈溢出

    TVersionInfo versionInfo( "HUAWEI MDSP R005C09L10303", "HUAWEI MDSP R005C09L10303 inner");

    cmMainctrl.setVersionInfo();

 

//CCMMainCtrl_Impl继承了会话管理类,会话类中会话数组初始化为100万,这个对象太大了,导致启动时就直接栈溢出了

9.   数据类型不一致,变量或参数赋值出错

ULONG useqId = authRsp.msgBody.nSequenceID;

snprintf(tmpSeqId, MaxTableNameLen,  "%s%d", pszIp, seqId);

pSession = dynamic_cast<TCManagerSession*>(TMainCtrl::instance()->getSession(tmpSeqId));

if (NULL == pSession)

{

    RUNLOG(TLogLevel_Debug, TLogID_PrintInfo, "pSession is NULL!");

}

 

//由于ULONG->int,数值越界,导致tmpSeqId有负值,进而getsession失败,一段时间内导致会话堆积,内存暴增

  

10.             分支流程未释放动态申请的内存

CMessage* pMsg;

NEW(pMsg, CVACUserOrderServiceReq);

 

TCode code

pMsg->decode(code)

if (False == sendToAplauncher(code))

{

    RUNLOG(TLogLevel_Error, TLogID_SocketSendFail,

           "Failed to send message to aplauncher.errno is %d", errno);

    return False;//此处没有释放pMSG,导致内存泄漏

}

DELETE(pMsg);

return True;

 

抱歉!评论已关闭.