内存泄露专题(1)何为内存泄露

简介: 内存泄露专题(1)何为内存泄露

作为C/C++的开发者,内存泄漏问题大概是最不愿意碰到,但是却不得不去面对的一个问题。自从C/C++诞生的那一天起,内存和指针就好比天上的两朵乌云,笼罩在无数C/C++开发者的头顶,如跗骨之蛆,挥之不去。它一方面以其无与伦比的高效率以及便捷性让人可以在浩如烟海的硬件地址之间纵横驰骋,如入无人之境;另一方面却又像一个娇滴滴的小姑娘,稍不顺心遂意,就会给你致命的下马威。就如同你永远猜不透女朋友为什么会生气一样,你永远也想不到在什么地方存在着看不见摸不着的内存泄漏问题。

高收益必然伴随着高风险,古人诚不欺我。

那么,什么是内存泄漏呢?

所谓内存泄漏,就是由于程序主动申请了内存,但是又没有主动释放它,那么这块内存可能就会一直驻留在进程中,只要进程不结束,内存就一直不释放。如果这是一个长期运行的server或者daemon类的守护进程,一旦发生内存泄漏,那么后果是不可设想,因为在长时间的运行过程中,进程一点点蚕食系统内存,最终可能导致系统内存耗尽,从而导致系统崩溃。

内存泄漏问题为什么会存在呢?

对于一个进程来说,其内存占用可根据其地址范围及生命周期分为四个区域,这就是大名鼎鼎的内存四区。分别为代码区、数据区、堆区和栈区。

其中代码区主要存放二进制代码,由操作系统进行管理;数据区主要存放全局变量、静态变量以及常量,这些变量 或常量会贯穿整个进程生命周期,在程序结束后会由操作系统进行释放。栈区的空间是由编译器自动分配和释放的 ,其生命周期一般以大括号{}作为分界点,比如常见的局部变量,函数参数等,大括号结束,变量空间也就自动释放了。以上三区的内存基本上都不会造成内存泄漏。

而真正会造成内存泄漏的罪魁祸首只有堆区内存。堆区的内存有个特点,就是必须由程序员手动去申请以及释放。比如常见的malloccallocrealloc函数用来在堆上申请内存,free函数用来释放内存。C++中也用new/delete运算符来管理申请和释放内存。通常来说,有申请就必须要有释放,也就是说,malloc/freenew/delete必然是成对出现的,一旦发生了不匹配 ,那么就极有可能存在内存泄漏问题。

void foo(){
    int *p = (void*)malloc(sizeof(int));
    //do  something with pointer p
    free(p);
    p = NULL;
}

比如上面就是一段非常简单的在堆上分配内存的例子,我们在第2行使用malloc函数在堆上申请了一个大小为 sizeof(int)的内存块,在第4行对这块内存进行了释放。

如果我们把第4行注释掉,代码如下所示:

void foo(){
    int *p = (void*)malloc(sizeof(int));
    //do  something with pointer p
    //free(p);
    p = NULL;
}

当执行完 p = NULL语句后,原来申请的那一块内存也就没有指针可以指向它了,但是这块内存又还没有释放,这样就会导致这块内存再也无法释放掉,除非整个进程停止。如果这样的代码在整个程序中有很多,那么也就会有很多内存申请后指针丢失,无法释放,导致内存占用越来越大,从而形成很严重的内存泄露问题。

那么,有人问,既然堆区的内存管理这么麻烦,而栈区的内存可以由编译器自动分配和回收。我们直接用栈区的内存不就行了吗?干嘛自讨苦吃,去招惹堆区的魔鬼呢?

事实上,每个进程所能使用栈空间是极其有限的。在Linux系统上,我们可以通过ulimit -s命令查看可支配的stack空间大小,这个大小一般只有几兆,甚至kb级别。对于一个大型的应用程序来说,这点可怜的栈区内存未免显得捉襟见肘。只有对那些占用内存比较小的变量,对执行效率要求比较高的地方,可能直接使用栈上的内容,对于一些比较占用内存的结构,比如结构体、字符串等,通常的做法,都是在堆上申请内存。

这也就意味着,只要我们使用C/C++进行编程,内存泄漏的问题就是我们不得不去面对并要解决的问题。


本专栏知识点是通过<零声教育>的系统学习,进行梳理总结写下文章,对C/C++课程感兴趣的读者,可以点击链接,查看详细的服务:C/C++Linux服务器开发/高级架构师

目录
相关文章
|
3月前
|
架构师 Unix Linux
内存泄露专题(4)mtrace内存追踪
内存泄露专题(4)mtrace内存追踪
36 0
|
3月前
|
架构师 C语言 C++
内存泄漏专题(2)如何判断程序有内存泄露
内存泄漏专题(2)如何判断程序有内存泄露
26 1
|
6月前
|
存储 缓存 监控
JVM第一讲:内存结构和内存分配,内存溢出和内存泄露
JVM第一讲:内存结构和内存分配,内存溢出和内存泄露
|
8月前
cocoscreator查内存泄露,绘制内存监视器
cocoscreator查内存泄露,绘制内存监视器
169 0
|
存储 缓存 算法
内存溢出、内存泄露的概述及常见情形
内存溢出、内存泄露的概述及常见情形
50735 3
内存溢出、内存泄露的概述及常见情形
|
弹性计算 运维 监控
如何解决 Linux 内核调测两大难题:内存被改与内存泄露
一直以来,内核内存调测领域一直持续存在着两大行业难题: "内存被改" 和 "内存泄漏"。内存问题行踪诡异、飘忽不定,在 Linux 内核的调测问题中,是最让开发者头疼的 bug 之一,因为内存问题往往发生故障的现场已经是第 N 现场了,尤其是在生产环境上出现,截止目前并没有一个很有效的方案能够进行精准的线上 debug,导致难以排查、耗时耗力。
453 0
如何解决 Linux 内核调测两大难题:内存被改与内存泄露
|
运维 Linux 开发者
Kernel SIG直播:让人头疼的“内核内存被改”和“内存泄露”怎么解?|第13期
内存发生故障问题让你抓狂?明天(周三)将有效地解决线上内核内存被改和内存泄露这两大难题。
Kernel SIG直播:让人头疼的“内核内存被改”和“内存泄露”怎么解?|第13期
|
Windows
进程结束后,进程的所有内存都将被释放,包括堆上的内存泄露的内存
进程结束后,进程的所有内存都将被释放,包括堆上的内存泄露的内存
996 0