0

0

Linux下内存问题排查利器

王林

王林

发布时间:2024-02-12 22:20:14

|

1287人浏览过

|

来源于良许Linux教程网

转载

1. 内存泄漏

内存泄漏(memory leak)是指程序中已动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。

Linux下内存问题排查利器

特点

  • 隐蔽性 因为内存泄漏的产生原因是内存块未被释放,属于遗漏型缺陷而不是过错型缺陷
  • 积累性 内存泄漏通常不会直接产生可观察的错误症状,而是逐渐积累,降低系统整体性能,极端的情况下可能使系统崩溃。最直观的问题就是为什么我们的程序开始运行正常,过段时间就异常退出。

内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于使用错误,导致在释放该段内存之前就失去了对该段内存的控制,从而造成了内存未释放而浪费掉。

产生的原因

磁力开创
磁力开创

快手推出的一站式AI视频生产平台

下载

我们在进行程序开发的过程使用动态存储变量时,不可避免地面对内存管理的问题。程序中动态分配的存储空间,在程序执行完毕后需要进行释放。没有释放动态分配的存储空间而造成内存泄漏,是使用动态存储变量的主要问题。一般情况下,作为开发人员会经常使用系统提供的内存管理基本函数,如malloc、realloc、calloc、free等,完成动态存储变量存储空间的分配和释放。但是,当开发程序中使用动态存储变量较多和频繁使用函数调用时,就会经常发生内存管理错误。

2. 如何排查内存泄漏

我们平时开发过程中不可避免的会遇到内存泄漏问题,这是常见的问题。既然发生了内存泄漏,我们就要排查内存泄漏的问题。想必大家也经常会用到以下排查内存问题的工具,如下:

  • memwatch
  • mtrace
  • dmalloc
  • ccmalloc
  • valgrind
  • debug_new

今天木荣不是介绍上面的排查工具,而是向大家介绍另一个内存泄漏排查工具:AddressSanitizer(ASan)。它支持 Linux、OS、Android等多种平台,不止可以检测内存泄漏,它是一个内存错误检测工具,可以检测很多常见的内存问题。

常见的内存问题检测:

  • 内存泄漏
  • 越界访问
  • 使用了释放的内存

3. AddressSanitizer(ASan)工具

Address Sanitizer(ASan) 是一个快速的内存错误检测工具。它非常快,只拖慢程序两倍左右(比起Valgrind快多了)。它包括一个编译器instrumentation模块和一个提供malloc()/free()替代项的运行时库。从gcc 4.8开始,AddressSanitizer成为gcc的一部分。当然,要获得更好的体验,最好使用4.9及以上版本,因为gcc 4.8的AddressSanitizer还不完善,最大的缺点是没有符号信息。

使用方法:

  • 用-fsanitize=address选项编译和链接你的程序。
  • 用-fno-omit-frame-pointer编译,以得到更容易理解stack trace。
  • 可选择-O1或者更高的优化级别编译
gcc -fsanitize=address -o main -g main.c

内存泄漏

#include 

void Fun()
{
    char *pM = malloc(10);
}

int main(int argc, char *argv[])
{
    Fun();
    return 0;
}

编译输出

图片

内存越界

  • 堆栈内存越界
#include 
#include 

void Fun()
{
    char *pM = malloc(10);
}

int main(int argc, char *argv[])
{
    //Fun();
    int *array = malloc(10*sizeof(int));
    if(array)
    {
            memset(array, 0, 10*sizeof(int));
    }
    int res = array[10];

    free(array);
    return 0;
}

运行输出

ubuntu@ubuntu:~/workspace_ex/Linux/ASan$ gcc -fsanitize=address -o main -g main.c
ubuntu@ubuntu:~/workspace_ex/Linux/ASan$ ls
main  main.c
ubuntu@ubuntu:~/workspace_ex/Linux/ASan$ ./main
=================================================================
==3234==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60400000dff8 at pc 0x000000400854 bp 0x7ffccc9253d0 sp 0x7ffccc9253c0
READ of size 4 at 0x60400000dff8 thread T0
    #0 0x400853 in main /home/ubuntu/workspace_ex/Linux/ASan/main.c:16
    #1 0x7fafc87a883f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2083f)
    #2 0x4006f8 in _start (/home/ubuntu/workspace_ex/Linux/ASan/main+0x4006f8)

0x60400000dff8 is located 0 bytes to the right of 40-byte region [0x60400000dfd0,0x60400000dff8)
allocated by thread T0 here:
    #0 0x7fafc8bea602 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98602)
    #1 0x4007f7 in main /home/ubuntu/workspace_ex/Linux/ASan/main.c:11
    #2 0x7fafc87a883f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2083f)

SUMMARY: AddressSanitizer: heap-buffer-overflow /home/ubuntu/workspace_ex/Linux/ASan/main.c:16 main
Shadow bytes around the buggy address:
  0x0c087fff9ba0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff9bb0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff9bc0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff9bd0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff9be0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c087fff9bf0: fa fa fa fa fa fa fa fa fa fa 00 00 00 00 00[fa]
  0x0c087fff9c00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff9c10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff9c20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff9c30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff9c40: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Heap right redzone:      fb
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack partial redzone:   f4
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
==3234==ABORTING
  • 全局内存越界
#include 
#include 

int g_nArray[10] = {0};

void Fun()
{
    char *pM = malloc(10);
}

int main(int argc, char *argv[])
{
    //Fun();

    /*
    int *array = malloc(10*sizeof(int));
    if(array)
    {
            memset(array, 0, 10*sizeof(int));
    }
    int res = array[10];

    free(array);
    */

    int nIndex = g_nArray[10];
    return 0;
}

运行输出

ubuntu@ubuntu:~/workspace_ex/Linux/ASan$ gcc -fsanitize=address -o main -g main.c
ubuntu@ubuntu:~/workspace_ex/Linux/ASan$ ls
main  main.c
ubuntu@ubuntu:~/workspace_ex/Linux/ASan$ ./main 
=================================================================
==4196==ERROR: AddressSanitizer: global-buffer-overflow on address 0x000000601128 at pc 0x00000040083e bp 0x7ffc8a332540 sp 0x7ffc8a332530
READ of size 4 at 0x000000601128 thread T0
    #0 0x40083d in main /home/ubuntu/workspace_ex/Linux/ASan/main.c:26
    #1 0x7fda216a583f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2083f)
    #2 0x400718 in _start (/home/ubuntu/workspace_ex/Linux/ASan/main+0x400718)

0x000000601128 is located 0 bytes to the right of global variable 'g_nArray' defined in 'main.c:4:5' (0x601100) of size 40
SUMMARY: AddressSanitizer: global-buffer-overflow /home/ubuntu/workspace_ex/Linux/ASan/main.c:26 main
Shadow bytes around the buggy address:
  0x0000800b81d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0000800b81e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0000800b81f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0000800b8200: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0000800b8210: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0000800b8220: 00 00 00 00 00[f9]f9 f9 f9 f9 f9 f9 00 00 00 00
  0x0000800b8230: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0000800b8240: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0000800b8250: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0000800b8260: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0000800b8270: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Heap right redzone:      fb
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack partial redzone:   f4
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
==4196==ABORTING
ubuntu@ubuntu:~/workspace_ex/Linux/ASan$ 

使用释放的内存

#include 
#include 
#include 

int g_nArray[10] = {0};
int *p;

void Fun()
{
    char *pM = malloc(10);
}

void Fun1()
{
    int nVar = 0;
    p = &nVar;
}

int main(int argc, char *argv[])
{
    //Fun();

    int *array = malloc(10*sizeof(int));
    if(array)
    {
            memset(array, 0, 10*sizeof(int));
    }
    int res = array[10];

    free(array);

    array[0] = 1;

    return 0;
}

运行输出

ubuntu@ubuntu:~/workspace_ex/Linux/ASan$ gcc -fsanitize=address -o main -g main.c
ubuntu@ubuntu:~/workspace_ex/Linux/ASan$ ./main
=================================================================
==4954==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60400000dff8 at pc 0x000000400b68 bp 0x7ffefbe3b170 sp 0x7ffefbe3b160
READ of size 4 at 0x60400000dff8 thread T0
    #0 0x400b67 in main /home/ubuntu/workspace_ex/Linux/ASan/main.c:28
    #1 0x7f1bbb78983f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2083f)
    #2 0x400928 in _start (/home/ubuntu/workspace_ex/Linux/ASan/main+0x400928)

0x60400000dff8 is located 0 bytes to the right of 40-byte region [0x60400000dfd0,0x60400000dff8)
allocated by thread T0 here:
    #0 0x7f1bbbbcb602 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98602)
    #1 0x400b0b in main /home/ubuntu/workspace_ex/Linux/ASan/main.c:23
    #2 0x7f1bbb78983f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2083f)

SUMMARY: AddressSanitizer: heap-buffer-overflow /home/ubuntu/workspace_ex/Linux/ASan/main.c:28 main
Shadow bytes around the buggy address:
  0x0c087fff9ba0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff9bb0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff9bc0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff9bd0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff9be0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c087fff9bf0: fa fa fa fa fa fa fa fa fa fa 00 00 00 00 00[fa]
  0x0c087fff9c00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff9c10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff9c20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff9c30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff9c40: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Heap right redzone:      fb
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack partial redzone:   f4
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
==4954==ABORTING
ubuntu@ubuntu:~/workspace_ex/Linux/ASan$

AddressSanitizer能检测的错误类型

错误类型 错误描述
(heap) Use after free 访问堆上已被释放的内存
Heap buffer overflow 堆上缓冲区访问溢出
Stack buffer overflow 栈上缓冲区访问溢出
Global buffer overflow 全局缓冲区访问溢出
Use after return 访问栈上已被释放的内存
Use after scope 栈对象使用超过定义范围
Initialization order bugs 初始化命令错误
Memory leaks 内存泄漏
  • 更多细节请访问官网

具体可以看 google 的官方文档:https://github.com/google/sanitizers/wiki/AddressSanitizer

结束语

ASan是个很好的检测内存问题的工具,不需要配置环境,使用还方便,编译时只需要-fsanitize=address -g 就可以, 运行程序时候可以选择添加对应的 ASAN_OPTIONS 环境变量就可以检测出很多内存问题。如果哪里不清楚可以查看官方说明,欢迎交流学习。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

395

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

575

2023.08.10

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

395

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

575

2023.08.10

overflow什么意思
overflow什么意思

overflow是一个用于控制元素溢出内容的属性,当元素的内容超出其指定的尺寸时,overflow属性可以决定如何处理这些溢出的内容。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

1755

2024.08.15

github中文官网入口 github中文版官网网页进入
github中文官网入口 github中文版官网网页进入

github中文官网入口https://docs.github.com/zh/get-started,GitHub 是一种基于云的平台,可在其中存储、共享并与他人一起编写代码。 通过将代码存储在GitHub 上的“存储库”中,你可以: “展示或共享”你的工作。 持续“跟踪和管理”对代码的更改。

762

2026.01.21

android开发三大框架
android开发三大框架

android开发三大框架是XUtil框架、volley框架、ImageLoader框架。本专题为大家提供android开发三大框架相关的各种文章、以及下载和课程。

284

2023.08.14

android是什么系统
android是什么系统

Android是一种功能强大、灵活可定制、应用丰富、多任务处理能力强、兼容性好、网络连接能力强的操作系统。本专题为大家提供android相关的文章、下载、课程内容,供大家免费下载体验。

1751

2023.08.22

Python 自然语言处理(NLP)基础与实战
Python 自然语言处理(NLP)基础与实战

本专题系统讲解 Python 在自然语言处理(NLP)领域的基础方法与实战应用,涵盖文本预处理(分词、去停用词)、词性标注、命名实体识别、关键词提取、情感分析,以及常用 NLP 库(NLTK、spaCy)的核心用法。通过真实文本案例,帮助学习者掌握 使用 Python 进行文本分析与语言数据处理的完整流程,适用于内容分析、舆情监测与智能文本应用场景。

10

2026.01.27

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL 教程
PostgreSQL 教程

共48课时 | 7.9万人学习

Git 教程
Git 教程

共21课时 | 3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号