面试问题:你工作中遇到的内存问题都是怎么解决的,使用什么工具,适用场景

面试问题:你工作中遇到的内存问题都是怎么解决的,使用什么工具,适用场景

背景

​ 肯定是出现了问题,主要的就是定位问题的所在

1. addr2line (用来查找访问保护地址NULL等)

​ 作用:将指定地址转换为对应的文件名和行号

1. 题外:当我们公司项目编写程序的时候,一般不让使用 abort函数来强制终止程序,我们都会 采取 **NULL**的值作为异常值返回当调用者使用、访问了这个异常的NULL的时候,就会发生错误,就方便我们定位了问题。如果置之不理,可能最终出现问题的地方和实际问题地方查了好远

2. 例子:
#include <stdio.h>

int main() {

    int* p = NULL;
    *p = (int)"main.c";
    return 0;
}

编译、运行 gcc main.c

输出:core dump

当一个大型的程序的时候,怎么搞?

就可以利用addr2line工具

  1. 步骤

    1. 对于 编译的时候需要加上 -g,表示输出有调试信息程序

      gcc -g main.c

    2. 开启core dump,默认是不开启的

      ulimit -c unlimited

    3. 运行程序,并生成崩溃的core文件

      ./a.out

    4. 读取core文件,获得IP寄存器

      demsg core

      得到异常发生的时候的地址

    700.663159] a.out[2315]: segfault at 0 ip 080483a9 sp bfc1c178 error 6 in a.out[8048000+1000]
    [  792.141021] a.out[2334]: segfault at 0 ip 080483a9 sp bfe9c3e8 error 6 in a.out[8048000+1000]
    
    
    1. 使用addr2line + 地址定位问题发生处

      addr2line 0x080483a9 -f -e ./a.out

经过上面的步骤,输出就是

main
/home/delphi/test/main.c:6

一下子就可以找到了

2. gdb + core (检查段错误)

步骤

  1. 对于 编译的时候需要加上 -g,表示输出有调试信息程序

    gcc -g main.c

  2. 开启core dump,默认是不开启的

    ulimit -c unlimited

  3. 运行程序,并生成崩溃的core文件

    ./a.out

  4. gdb运行程序 + core

    gdb ./a.out core

    得到异常发生的时候的地址

9 in main () at main.c:6
6	    *p = (int)"123";

3. valgrind(检查内存泄漏、重复释放)

​ 作用:对可执行程序进行 内存泄漏检查

​ 使用方法:
​ valgrind --tool=memcheck --leak-check=yes 可执行程序名称

​ 当有错误就会出现下面的提示

==2545== HEAP SUMMARY:
==2545==     in use at exit: 4 bytes in 1 blocks
==2545==   total heap usage: 1 allocs, 0 frees, 4 bytes allocated
==2545== 
==2545== 4 bytes in 1 blocks are definitely lost in loss record 1 of 1
==2545==    at 0x4025BD3: malloc (vg_replace_malloc.c:236)
==2545==    by 0x80483D8: main (main.c:5)
==2545== 
==2545== LEAK SUMMARY:
==2545==    definitely lost: 4 bytes in 1 blocks
==2545==    indirectly lost: 0 bytes in 0 blocks
==2545==      possibly lost: 0 bytes in 0 blocks
==2545==    still reachable: 0 bytes in 0 blocks
==2545==         suppressed: 0 bytes in 0 blocks

4. cppcheck (静态解析程序中有问题的地方 空地址访问、内存泄漏)

一般直接使用 cppcheck xx文件,可以用的有*.cpp, *.cxx, *.cc, *.c++ and *.c files,或者直接给 文件夹

参数有:

  1. --enable=id Enable additional checks. The available ids are:

    all - enable all checks
    exceptNew - exception safety when using new

    exceptRealloc - exception safety when reallocating

    style - Check coding style
    unusedFunctions - check for unused functions

  2. --file-list=file Specify the files to check in a text file. One Filename per line

  3. -I [dir] Give include path. Give several -I parameters to give
    several paths. First given path is checked first. If
    paths are relative to source files, this is not needed

5. 进行 系统调用 分析

​ strace常用来跟踪进程执行时的系统调用和所接收的信号。 在Linux世界,进程不能直接访问硬件设备,当进程需要访问硬件设备(比如读取磁盘文件,接收网络数据等等)时,必须由用户态模式切换至内核态模式,通过系统调用访问硬件设备。strace可以跟踪到一个进程产生的系统调用,包括参数,返回值,执行消耗的时间。

  1. 输出参数的含义

    每一行都是一条系统调用,等号左边是系统调用的函数名及其参数,右边是该调用的返回值。 strace 显示这些调用的参数并返回符号形式的值。strace 从内核接收信息,而且不需要以任何特殊的方式来构建内核

    1. 跟踪可执行程序

    strace -f -F -o ~/straceout.txt myserver

    -f -F选项告诉strace同时跟踪fork和vfork出来的进程,-o选项把所有strace输出写到~/straceout.txt里 面,myserver是要启动和调试的程序

    1. 跟踪服务程序

    strace -o output.txt -T -tt -e trace=all -p 28979

    跟踪28979进程的所有系统调用(-e trace=all),并统计系统调用的花费时间,以及开始时间(并以可视化的时分秒格式显示),最后将记录结果存在output.txt文件里面

6. 根据进程号得到 堆栈信息

​ 我们有的时候只知道 一个 pid出了问题,但是不清楚 问题点在哪里(死锁?)

​ 可以使用pstack 工具来实现

​ 使用方法:

​ pstack pid

​ 结果就是

#0  0x00007f50ff291774 in __GI___nanosleep (requested_time=requested_time@entry=0x7ffe89b2ec90, remaining=remaining@entry=0x7ffe89b2ec90) at ../sysdeps/unix/sysv/linux/nanosleep.c:28
#1  0x00007f50ff29167a in __sleep (seconds=0) at ../sysdeps/posix/sleep.c:55
#2  0x000000000040056f in main ()

​ 如果不可用参见pstack无法使用的问题_笔记本专栏-CSDN博客

5. 上面的都是针对已知程序进行分析,那如果不知道呢

1. 第一种推荐 top

​ 系统响应变慢,首先得定位大致的问题出在哪里,是IO瓶颈、CPU瓶颈、内存瓶颈还是程序导致的系统问题

  1. 终端输入:top

  2. 进入交互模式后:

    输入M,进程列表按内存使用大小降序排序,便于我们观察最大内存使用者使用有问题(检测内存泄漏问题);

    输入P,进程列表按CPU使用大小降序排序,便于我们观察最耗CPU资源的使用者是否有问题;

    1. top第三行显示当前系统的,其中有两个值很关键

    %id:空闲CPU时间百分比,如果这个值过低,表明系统CPU存在瓶颈;

    %wa:等待I/O的CPU时间百分比,如果这个值过高,表明IO存在瓶颈;

2. free

​ 检查当前可用的内存,

​ 但是这个只能发现内存越来越少,不知道对应的pid是啥

​ 系统实际可用的内存为free工具输出第二行的free+buffer+cached;

可用的内存越来越少也就出了问题

posted @ 2021-05-01 18:39  make_wheels  阅读(165)  评论(0编辑  收藏  举报