天天看点

内存泄漏、内存溢出、内存越界、段错误、堆溢出、栈溢出

内存泄露

内存泄漏(memory leak)是应用程序分配某段内存后,由于疏忽或者错误,失去了对该段内存的控制,因而造成了内存的浪费。
或者可以说向系统申请分配内存进行使用(new),但是用完后不归还(delete),导致占用有效内存。
简而言之:调用了malloc/new等申请内存的操作,但是缺少了对应的free/delete操作。
           

内存溢出

内存溢出就是要求分配的内存超出了系统所给的。要求的超出分配的。
主要有:堆溢出、 栈溢出、内存永久保护区溢出
内存溢出原因:

(1)内存中加载的数据量过于庞大,如一次性从数据库取出过多数据。

(2)集合类中有对对象的引用,使用后未清空,使得不能回收。

(3)代码中存在死循环或循环产生过多重复的对象实体。

(4)使用的第三方软件中的bug

(5)启动参数内存值设定的过小
           

栈溢出

栈溢出就是由于递归或循环嵌套层次太多造成的。
1)局部数组过大。当函数内部的数组过大时,有可能导致栈溢出。
2)递归调用层次太多。递归函数在运行时会执行压栈操作,当压栈次数太多时,也会导致栈溢出。
3)指针或数组越界。这种情况最常见,例如进行字符串拷贝,或处理用户输入等等。
           

栈中分配局部变量空间,堆区是向上增长的用于分配程序员申请的内存空间。具体查内存分配。

栈使用的是一级缓存, 他们通常都是被调用时处于存储空间中,调用完毕立即释放。

堆则是存放在二级缓存中,生命周期由虚拟机的垃圾回收算法来决定(并不是一旦成为孤儿对象就能被回收)。所以调用这些对象的速度要相对来得低一些。

堆溢出

堆是程序员自己创建的,通常来说,导致堆溢出的操作是不断的new 一个对象,一直创建新的对象,但是不销毁。
           

内存越界

是指向系统申请一块内存后,使用时却超出申请范围。比如一些操作内存的函数:sprintf、strcpy、strcat、vsprintf、memcpy、memset、memmove。当造成内存泄漏的代码运行时,所带来的错误是无法避免的,通常会造成
1.破坏了堆中内存内存分配信息数据
2.破坏了程序其他对象的内存空间
3.破坏了空闲内存块	
           

段错误

“段”(Segment)是指二进制文件内的区域,所有某种特定类型信息被保存在这里。可以用size程序得到可执行文件中各个段的大小。
C程序布局中分为代码段、初始化数据段、非初始化数据段、栈段和堆段。

段错误就是访问了不可访问的内存,这个内存区要么是不存在的,要么是受到系统保护的,还有可能是缺少文件或者文件损坏。
段错误产生典型的原因
非关联化空指针——这是特殊情况由内存管理硬件
试图访问一个不存在的内存地址(在进程的地址空间)
试图访问内存的程序没有权利(如内核结构流程上下文)
试图写入只读存储器(如代码段)
           

继续阅读