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 编程规范性问题

  在进行软件开发前,首先需要制定企业的编程规范,然后根据编程规范,列出需要重点改进的编程规范性问题列表,程序员根据编程规范进行编码,代码测试人员在进行单元测试时,也要根据编程规范进行审查,这样可以大大提高代码的可读性和可移植性,并且降低风险和减少后期维护成本。