在C\C++编程时常范的低级错误总结
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在C\C++编程时常范的低级错误总结相关的知识,希望对你有一定的参考价值。
大学毕业快两年,也当快两年的码农,最近在总结下自己在两年中编程时常范的低级错误。
1、宏里面有return语句
如:
#define ACE_NEW_RETURN(POINTER,CONSTRUCTOR,RFT_VAL) \
Do{ \
POINTER = new CONSTRUCTOR; \
If(POINTER ==NULL) \
{ \
Return RFT_VAL;\
} \
}
当执行如下语句时:
ACE_NEW_RETURN(g_Proctimer,CONSTRUCTOR,RFT_VAL);
ACE_NEW_RETURN(g_Proctimer,CONSTRUCTOR,RFT_VAL);
当第二个宏语句在宏里出现错误直接return时,第一个ACE_NEW_RETURN语句中申请的内存就泄漏了。
防范:小心使用有return语句的宏,确保前面资源已经释放。
2、异常出口处没有释放内存、定时器、文件句柄、socket、队列、信号量、GUI等资料。
如:
pMsgDBapp_To_Logic1= lppdbself();//申请资源
If(pMsgDBapp_To_Logic1 == NULL)
{
Return;
}
pMsgDBapp_To_Logic2= lppdbself();//申请资源
If(pMsgDBapp_To_Logic2 == NULL)
{
Return;
}
问题定位:在第2个return处,pMsgDBapp_To_Logic1指向的内存丢失。
防范:
看见return要注意,要去前面找资源特别要注意链表等数据结构中的资源。
3、没有释放数据组的成员指针。
Struct dirent **namelist;
Int n = scandir(path_c_str(),&namelist,0,alphsorc);
Int i = 0;
For(i = 0; i < n;++i)
{
String name = namelist[i]->name;
Free(namelist[i]->name);
If(name !=”..” && name !=”,”)
{
++fileNum;
}
If(MAX_SACN_FILE_NUM == fileNum)
{
Break;
}
Free(namelist);
Return;
}
如果大于1000,就会导致内存泄漏。
防范:
在使用指针数组时,特别注意确保在释放数组时,数组中的每个元素指针是否已经提前被释放,这样才不会导致致内存泄漏。
4、非空指针作为左值需要释放的指针参与运算;
While(NULL != LPSRCSTR())
{
LPSRCSTR = LPSRCSTR +1;
LPSRCSTR = LPBACKSTR;
}
Free(LPSRCSTR );
问题:LPSRCSTR 参与运算后,指向的地址不是原来最初使用malloc申请的内存了。
防范:使用临时变量参与指针运算,确保原来指针不会被修改,需要释放的指针禁止参与运算。
5、重复分配内存。
在拷贝别人的代码时,有时代码中有分配资源的情况
6、使用复杂的语句或函数,没有及时资源,在编程时,我们应该要养成及时释放内存和资源的习惯。
7、在使用复杂的函数,一个语句,多个分配。
如:
FUNC(shared_ptr<widget>(new widget),shared_ptr<widget>(new widget));
函数func的两个入参是智能指针,会被自动回收。通常不可能出现内存泄漏的情况。但是,不同的编译器处理可能不一样,编译器可能将上面代码细化操作为:
(1)对第一个参数执行new widget分配内存
(2)对第二个参数执行new widget分配内存
(3)对第一个参数进行初始化
(4)对第二个参数进行初始化
如果第三步出现了异常,第一步分配的内存被回收了,但是第二步申请的内存泄漏了。
8、没有释放队列中的内存
处理链表或队列时,如果删除了其中的一个节点,还必须同时释放节点申请的内存。
9、强制关闭线程:没有释放线程占据的资源,使用事件或信号量通知线程,确保线程调用自身的既出函数。
以上是关于在C\C++编程时常范的低级错误总结的主要内容,如果未能解决你的问题,请参考以下文章