深入探究 Linux C中进程崩溃

目录

前言
栈内存异常以及案列分享
堆内存异常以及案列分享
Ptmalloc的内存管理

前言

LinuxC的内存管理融入了设计者很多高效的算法和思想,提供了用户直接可以操作的内存的“指针”,这也是其他语言不涉及的(除Go语言21世纪的C语言),但是对于指针这把双刃剑,开发者操作着进程的内存,难免造成意想不到的崩溃问题,其实踩内存情况应该把栈和堆(ptmalloc)分开,因为linux对这两块的管理机制不同,本次讨论栈空间内存异常以及堆内存异常导致的崩溃问题,重点提供定位思路,关于泄露和锁问题后期可以继续研究。
在这里插入图片描述

栈内存异常以及案列分享

  • 访问空指针
  • 原因:访问空指针,导致崩溃
    空指针原因:互操作、非原子操作导致定时器链表节点为空,导致pstTmpTimer 为NULL
  • 总结:对于函数返回值为指针类型的,在使用时候,应该判断是否为NULL情况,被调函数指针值尽可能可控
    在这里插入图片描述在这里插入图片描述
  • 栈中局部变量内存地址被踩,不可预料
  • 原因:拷贝的数据长度多了,覆盖了栈帧中局部变量中的值,修改了pstChlVodStausRspMsg 的地址,导致造成了非法访问
    总结:对于系统函数或库函数,特别是入参是指针且操作内存的函数,函数入参要谨慎细微,如atoi() 、strcpy()、 memcpy()、popen()、scanf()等。
    在这里插入图片描述在这里插入图片描述
    在这里插入图片描述
  • 访问非法地址,不可预料
    在这里插入图片描述在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 栈内存访问非法总结:
    1.栈内存异常导致的崩溃定位难度比较简单,首先必现,不会随机崩溃,多线程环境下也仅仅是自己的线程空间中的函数栈。Ps:有一些内存发生堆叠、造成的雪崩,会导致函数栈完全破坏,这种就比较麻烦。

定位方法:
1.首选gdb,毕竟不是随机崩溃,所以大多都可以直接调试出来。
2.跑检测工具。
3.定位流程,注销代码,缩小范围,打印日志。

堆内存异常以及案列分享

  • 随机崩溃(一):malloc的内存被越界,地址被修改,导致地址非法,暂时不崩溃,在free 时候不崩溃 ,等下次谁去malloc 时候崩溃

  • 定位过程:
    1.堆栈最后出现 glibc 的 _int_malloc()函数,需要注意,此时的内存是由于之前free的内存块被踩 ,下面是init_malloc()函数的异常,都会触发abort()函数发生崩溃
    在这里插入图片描述

  • 2.既然是free出的问题,那就打印了dump中的所有的线程栈,找带有free的堆栈,判断free 内存的异常是自己的函数栈还是其他线程栈空间,通常有两种,1.在自己的线程栈中,申请的内存,free 前被踩了,那么会挂自己线程栈空间 ,如果其他线程空间,需要打印所有的线程栈空间
    在这里插入图片描述

  • 3.结合代码,排除嫌疑,找这块代码申请内存的地方,pstAuthInfo 这个指针指向的是动态开辟的所以打印指针内容,需要特别注意 这个szQop 这个字段gdb没有提示类似 ‘\000’ <repeats 43 times> ,说明此数组已经填满

  • 4.打印证明是否是数组越界,证明确实是数组越界了,数组最后的\0 都踩了,数组没有结束符, 这个数组的内存是malloc的结构体,那就free 的时候已经非法了。
    在这里插入图片描述在这里插入图片描述总结:
    字符串的这种匹配,往数组放内容,数据入参异常的时候就会出问题,可以增加szQop[strlen(szQop) - 1] = ‘\0’,进行保护。

  • 随机崩溃(二):malloc的内存,指针修改地址越界,导致free 时候崩溃 ,或下次谁去malloc 时候崩溃的随机崩溃
    在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
    1.堆内存的申请的数据块,如果使用者进行了非法操作,导致的问题比较难定位,特别在多线程环境下,会产生随机崩溃,线程数量越多,跟踪定位就越困难。
    2.因为ptmalloc支持多线程的原因,把所有的线程申请的动态内存统一维护队列中,这样就会出现直接gdb的bt,堆栈往往不在此刻线程中。
    3.内存的回收机制、申请机制比较复杂,可能异常的内存回收缓存的trunk 中,下次给其他线程分配时候,检测发生崩溃。

定位方法:
1.需要对地址敏感,对堆栈可以有大体的把握,列如,顶层堆栈出现了_int_malloc()字样,就去找其他线程中有free()的堆栈。
2.工具定位,实在定位不出来,还是跑工具进行协助定位。

Ptmalloc的内存管理

Ptmalloc是目前glibc 的堆内存管理,开发者使用的free()和malloc()在ptmalloc 中它特有的算法以及机制,学习ptmalloc 原理有利于:
1.知道动态内存的分配、调度、使用、释放过程,从而gdb 看堆栈时候,在多线程环境下,在很多堆栈中,寻找怀疑的线程栈。
2.知道动态内存使用需要谨慎细微,glibc的堆管理高效性,基于开发者对内存的正确使用。
3.更好学习指针的使用,其中ptmalloc有大量的指针运算,提升自己。

发布了205 篇原创文章 · 获赞 47 · 访问量 26万+

猜你喜欢

转载自blog.csdn.net/qq_32744005/article/details/105718398