深入探究 Linux C中进程崩溃

时间:2024-03-20 11:40:20

目录

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

前言

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

栈内存异常以及案列分享

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

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

堆内存异常以及案列分享

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

  • 定位过程:
    1.堆栈最后出现 glibc 的 _int_malloc()函数,需要注意,此时的内存是由于之前free的内存块被踩 ,下面是init_malloc()函数的异常,都会触发abort()函数发生崩溃
    深入探究 Linux C中进程崩溃

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

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

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

  • 随机崩溃(二):malloc的内存,指针修改地址越界,导致free 时候崩溃 ,或下次谁去malloc 时候崩溃的随机崩溃
    深入探究 Linux C中进程崩溃深入探究 Linux C中进程崩溃深入探究 Linux C中进程崩溃深入探究 Linux C中进程崩溃
    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有大量的指针运算,提升自己。