【C语言】段错误、内存溢出、内存泄漏(区别)、堆溢出、栈溢出
段错误
什么时候会发生段错误?
段错误通常发生在访问非法内存地址的时候,即使用了野指针(指向一个已删除的对象或者未申请访问受限内存区域的指针)或这试图修改字符串常量的内容。
内存溢出
内存溢出和内存泄漏的区别:https://v.douyin.com/MpQWyac/
- 内存溢出指的是程序去申请内存时,没有足够的内存空间让他去使用,有的程序执行会直接就报out of memory超出内存的一个提示,这个和网盘空间不足是一个道理。
- 内存泄漏它指的是程序去申请内存后,他没释放他已经申请的内存空间。比方说程序执行了一个死循环代码,每执行一次代码,它就会申请新的一个内存空间,程序又没法正常的退出循环,他就会不断地占用更多的内存空间。无论程序有多少内存,它迟早会被占光,所以说内存泄漏最终也会导致内存溢出。
内存溢出指程序在申请内存时,没有足够的内存供申请者使用。内存溢出就是程序员要申请的内存空间超过了系统实际能够分配给你的空间,此时系统相当于没法满足程序员的需求,就会报内存溢出的错误。
内存溢出原因:
(1)内存中加载的数据量过于庞大,如一次性从数据库取出过多数据。
(2)集合类中有对对象的引用,使用后未清空,使得不能回收。
(3)代码中存在死循环或循环产生过多重复的对象实体。
(4)使用的第三方软件中的bug
(5)启动参数内存值设定的过小
内存泄漏
内存泄漏(memory leak)是指由于疏忽或错误造成了程序未能释放掉不再使用的内存的情况。内存泄漏并非指内存在物理意义上的消失,而是应用程序分配某段内存后,由于设计错误,失去了对该段内存的控制,因而造成了内存的浪费。
内存泄漏的分类:
(1)堆内存泄漏(heap leak):堆内存指的是程序在运行中根据通过malloc/new等从堆中分配的一块内存,使用完成后必须通过调用相对应的free/delete释放掉。如果程序设计的错误导致这部分内存没有被释放掉,那么此后这块内存将不会被使用,就会产生堆内存泄漏。
(2)系统资源泄漏(resource leak):主要指程序使用系统分配的资源比如bitmap、handle、socket等没有使用相应的函数释放掉,导致系统资源的浪费,严重时可导致系统性能降低,运行不稳定。
(3)没有将基类的析构函数定义为虚函数。当基类指针指向派生类的对象时,如果基类的析构函数不是虚函数,那么子类的析构函数将不会被调用,子类的资源没有被正确释放掉,因此造成内存泄漏。
如何判断内存泄漏?
内存泄漏通常是由于调用了malloc/new等申请内存的操作,但是缺少了对应的free/delete操作。为了判断内存泄漏,我们可以使用linux下的内存泄漏检查工具来判断内存是否泄漏,除此之外,我们可以在写代码时添加内存申请和释放的统计功能,来统计当前申请和释放的内存是否一致,从而来判断内存是否泄漏。
栈溢出
一般通俗来说,栈溢出就是由于递归或循环嵌套层次太多造成的。在平时的编程中,造成栈溢出的现象主要有以下几种:
(1)局部数组过大。当函数内部的数组过大时,有可能导致栈溢出。
(2)递归调用层次太多。递归函数在运行时会执行压栈操作,当压栈次数太多时,也会导致栈溢出。例如,在解决斐波那契数列时,采用递归法求第1000项的斐波那契数时,往往会造成栈溢出。
(3)指针或数组越界。这种情况最常见,例如进行字符串拷贝,或处理用户输入等等。
针对以上现象的解决办法有:一是增大栈空间,二是改用动态分配,使用堆(heap)而不是栈(stack)。
堆溢出
通常来说,导致堆溢出的操作是不断的new 一个对象,一直创建新的对象,但是不销毁。
栈溢出和堆溢出区别
栈溢出(Stack Overflow)和堆溢出(Heap Overflow)是两种不同类型的内存溢出问题,发生在计算机程序的不同内存区域。栈溢出 (Stack Overflow):
-
发生位置: 栈(Stack)是用于存储函数调用和局部变量的内存区域。栈溢出指的是当函数调用的层次过深,导致栈空间不足时发生的问题。
-
原因: 通常由于递归函数调用过深或者函数调用没有正确的返回,导致栈空间耗尽。
-
特征: 常见的错误是堆栈溢出(Stack Overflow)异常,程序可能崩溃并显示类似 “Stack Overflow” 的错误消息。
-
修复: 避免无限递归调用,确保递归调用有正确的结束条件,或者增加栈的大小(这通常是通过调整操作系统或编译器的设置来完成)。
堆溢出 (Heap Overflow):
-
发生位置: 堆(Heap)是用于动态分配内存的区域,通常由
malloc
、free
等函数管理。堆溢出指的是对动态分配的内存进行越界访问,或者写入超出分配内存范围的数据。 -
原因: 通常由于对已经释放的内存进行操作、数组越界、指针错误等问题引起。
-
特征: 堆溢出可能导致程序崩溃,或者在不同的时候产生不可预测的行为。它可能被利用成为安全漏洞的一部分,例如缓冲区溢出攻击。
-
修复: 使用动态分配的内存时,确保对内存的访问不越界,正确释放不再需要的内存。在C语言中,可以使用工具如Valgrind等来检测内存溢出问题。
总的来说,栈溢出和堆溢出都是由于对不同内存区域的错误使用而引起的问题。在编写程序时,要注意避免递归调用过深,确保栈的合理使用,同时在使用动态内存时要小心避免越界访问等问题。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!