由于身体不舒服,再加上去华为实习没时间。太久没有更新学习比笔记了,希望能保持记录学习中的点点滴滴小知识
内存溢出:(Out Of Memory---OOM)
系统已经不能再分配出你所需要的空间,比如你需要100M的空间,系统只剩90M了,这就叫内存溢出
例子:一个盘子用尽各种方法只能装4个果子,你装了5个,结果掉倒地上不能吃了。这就是溢出。比方说栈,栈满时再做进栈必定产生空间溢出,叫上溢,栈空时再做退栈也产生空间溢出,称为下溢。就是分配的内存不足以放下数据项序列,称为内存溢出。说白了就是我承受不了那么多,那我就报错。
内存泄漏: (Memory Leak)
是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。
一般我们所说的内存泄漏是指堆内存的泄漏,堆内存是指程序从堆中分配的,大小任意的(内存块的大小可以在程序运行期决定),使用完成之后必须显示释放内存。应用程序一般使用malloc、realoc、new等函数从堆中分配到一块内存块,使用完成后,程序必须负责相应的释放。在C中使用free(),C++中delete、delete[]、free()
例子:你向系统申请分配内存进行使用(new),可是使用完了以后却不归还(delete),结果你申请到的那块内存你自己也不能再访问(也许你把它的地址给弄丢了),而系统也不能再次将它分配给需要的程序。就相当于你租了个带钥匙的柜子,你存完东西之后把柜子锁上之后,把钥匙丢了或者没有将钥匙还回去,那么结果就是这个柜子将无法供给任何人使用,也无法被垃圾回收器回收,因为找不到他的任何信息。
内存越界
是指向系统申请一块内存后,使用时却超出申请范围。
Ø 数组越界
数组越界错误主要包括数组下标取值越界和指向数组的指针的指向范围越界。
Ø 避免操作内存的函数造成越界:
比如sprintf、strcpy、strcat、vsprintf、memcpy、memset、memmove。在编程军规中也有明确的规定。如下:
【军规4 】:内存拷贝前必须进行长度有效性判断,避免内存越界
引申:避免使用魔鬼数字来进行人工计算字符长度,引起内存越界。
例如:memcpy_s
复制源缓冲区的数据到目的缓冲区。
errno_t memcpy_s(
void* dest,
size_t destMax,
const void* src,
size_t count
)
参数
dest
[In/Out] 目的缓冲区
destMax
[In] 目的缓冲区大小
src
[In]源缓冲区
count
[In] 从源缓冲区中复制的字符数
错误码
其它情况,操作成功,返回值EOK(0)。
注意
-
确保入参正确:
a. 拷贝长度参数和目的缓冲区大小参数要大于0且小于等于SECUREC_MEM_MAX_LEN;
b. 目的缓冲区大小参数不能超过目的缓冲区的实际长度、且大于等于要拷贝长度,以便目的缓冲区有足够的空间来保存要复制的内容;
c. 源缓冲区和目的缓冲区不能为NULL、且源和目的不存在重叠。
2、调用函数时,必须对返回值进行检查,确保返回值正确后再进行后续操作。
注意:在源缓冲区为NULL、拷贝长度大于目的缓冲区大小参数、源和目的重叠的情况下,函数会将目的缓冲区大小参数确定的目的缓冲区范围清零。
之所以会对安全函数整改,需要明确不是使用了安全函数就绝对安全。安全函数安全性基于调用者传入了正确参数,特别是缓冲区长度一定要正确。安全函数将传入的长度参数作为缓冲区的边界,只保证执行结果不会溢出用户所指定的边界。如果传入的缓冲区长度参数超过实际缓冲区大小,依然可能会溢出。
如下就是目的缓冲区pucBlock的大小有问题,memcpy中为了方便,很多都写成了2,4参数一致。这样就存在2参数不是1参数的实际大小。虽然在拷贝的时候可能不会出现问题,但为了安全还是应该认真检查四个参数,并确保使用正确。
修改前: iRet = memcpy_s( (VOS_VOID *)pucBlock,IPV6_ADDR_LEN, (VOS_VOID *)pucIpV6, IPV6_ADDR_LEN );
修改后:iRet = memcpy_s( (VOS_VOID *)pucBlock, DB_IP_PORT, (VOS_VOID *)pucIpV6, IPV6_ADDR_LEN );