2.2.3 sqlite_exec()函数使用问题
使用sqlite_exec()函数后,没有判断返回值,对errmsg指针进行释放;使用sqlite_get_table()后,异常退出时,没有释放获取的table信息,由于在进行函数调用的时候,隐式的获取了资源,所以,在异常退出时,容易忽略对资源的回收处理,例如:
…… sprintf( sqlop, "select meter_addr from IMPORTANT_METER;" ); rc = sqlite3_get_table( sqldb , sqlop, &azResult , &nrow , &ncolumn , &zErrMsg ); if( rc != SQLITE_OK ) { sqlite3_close( sqldb ); return false; |
====>>>>ruturn false时,必须sqlite3_free_table( azResult )释放获取的table信息,避免内存泄露;同时,还需要调用sqlite3_free( zErrMsg ),释放zErrMsg信息,避免内存泄露
2.2.4 new内存后,异常返回时,没有delete 内存
在使用new申请动态内存后,如果遇到异常情况返回时,没有使用delete释放内存,之前该内存依然被占用,这个问题在程序运行的短时间内可能不会体现,但是如果该操作时在循环内执行,在长时间运行后,系统内存将被大量占用,可能导致系统运行缓慢甚至崩溃,例如:
void PrOAFN04::get_fntable(unsigned int fn) { FnJZ_table* m_pList =new FnJZ_table[MAXTABLE]; memset(m_pList,0x00,MAXTABLE*sizeof(FnJZ_table)); int m_num = 0; CArchive m_Archive( STATINI, EXTREMUMID); if(m_Archive.GetIdArch((unsigned char) fn, m_pList, m_num)) { m_pFnJZ_table =m_pList; } |
====>>>>如上if判断,应该加上else分支,GetIdArch方法操作失败时,应该delete m_pList资源,不然就存在内存泄露
2.3 数组访问越界
数组访问越界问题是一个非常严重的问题,在程序运行时,它的表现是不定的,有可能程序会正常运行,有时候可能会导致系统突然崩溃,如果在程序开发阶段没有发现这个问题,一旦产品流入市场,它就会像一颗定时炸弹,随时可能造成无法估量的后果。数组越界主要表现在以下几个方面:指针变量地址访问越界、循环变量失控,导致越界、循环变量与数组元素数量没有关联,导致明显访问越界、代码编写时,拷贝引起的笔误导致数组访问越界等,例如:
bool CShmMemory::ShmGet( int CreatMode, int AttchMod ) { …… char *p = (char * )pshmaddr; if( *p != 1 && (IPC_CREAT & CreatMode) ) { memset( p + 1, 0xFF, m_shm_size); |
===>>>p指向共享内存的首地址,初始化时,如果从p+1开始,那么最多只能写(m_shm_size-1)个字节,这里的初始化赋值语句明显访问越界了
……
2.4 编程规范性问题
在进行软件开发前,首先需要制定企业的编程规范,然后根据编程规范,列出需要重点改进的编程规范性问题列表,程序员根据编程规范进行编码,代码测试人员在进行单元测试时,也要根据编程规范进行审查,这样可以大大提高代码的可读性和可移植性,并且降低风险和减少后期维护成本。