内存泄漏的场景分析和避免方法总结,C语言内存泄漏详解
发布时间:2020-12-15 17:32:43 所属栏目:百科 来源:网络整理
导读:大家都知道,在堆上分配的内存,如果不再使用了,就应该及时释放,以便后面其他地方可以重用。而在 C 语言中,内存管理器不会自动回收不再使用的内存。如果忘了释放不再使用的内存,这些内存就不能被重用了,这就造成了 内存泄漏 。 内存泄漏几乎是很难避免的
大家都知道,在堆上分配的内存,如果不再使用了,就应该及时释放,以便后面其他地方可以重用。而在 C 语言中,内存管理器不会自动回收不再使用的内存。如果忘了释放不再使用的内存,这些内存就不能被重用了,这就造成了内存泄漏。 内存泄漏几乎是很难避免的,不管是老手还是新手,都存在这个问题,甚至 Windows 与 Linux 这类系统软件也或多或少存在着内存泄漏。 也许对一般的应用软件来说,这个问题似乎不是那么突出与严重。一两处内存泄漏通常并不致于让程序崩溃,也不会带来逻辑上的错误,而且在进程退出时,系统会自动释放所有与该进程相关的内存(共享内存除外),所以内存泄漏的后果相对来说还是比较温和的。但是,量变会导致质变,一旦内存泄漏过多以致耗尽内存,后续内存分配将会失败,程序就可能因此而崩溃。 在常见情况下,内存泄漏的主要可见症状就是罪魁进程的速度减慢。原因是体积大的进程更有可能被系统换出,让别的进程运行,而且大的进程在换进换出时花费的时间也更多。即使泄漏的内存本身并不被引用,但它仍然可能存在于页面中(内容自然是垃圾),这样就增加了进程的工作页数量,降低了性能。 下面展示了一些导致内存泄漏的常见场景。 1) 指针重新赋值看下面一段示例代码:char * p = (char *)malloc(10); char * np = (char *)malloc(10);其中,指针变量 p 和 np 分别被分配了 10 个字节的内存,它们各自的内存如图 1 所示。 图 1 p 和 np 赋值前的内存 如果程序需要执行如下赋值语句: p=np;这时候,指针变量 p 被 np 指针重新赋值,其结果是 p 以前所指向的内存位置变成了孤立的内存,如图 2 所示。它无法释放,因为没有指向该位置的引用,从而导致 10 字节的内存泄漏。 图 2 p 和 np 赋值后的内存 因此,在对指针赋值前,一定确保内存位置不会变为孤立的。 2) 错误的内存释放假设有一个指针变量 p,它指向一个 10 字节的内存位置。该内存位置的第三个字节又指向某个动态分配的 10 字节的内存位置,如图 3 所示。图 3 p 所指向的内存 如果程序需要执行如下赋值语句时: free(p);很显然,如果通过调用 free 来释放指针 p,则 np 指针也会因此而变得无效。np 以前所指向的内存位置也无法释放,因为已经没有指向该位置的指针。换句话说,np 所指向的内存位置变为孤立的,从而导致内存泄漏。 因此,每当释放结构化的元素,而该元素又包含指向动态分配的内存位置的指针时,应首先遍历子内存位置(如本示例中的 np),并从那里开始释放,然后再遍历回父节点,如下面的代码所示: free(p->np); free(p); 3) 返回值的不正确处理有时候,某些函数会返回对动态分配的内存的引用,如下面的示例代码所示:char *f() { return (char *)malloc(10); } void f1() { f(); }很明显,函数 f1 中对 f 函数的调用并未处理该内存位置的返回地址,其结果将导致 f 函数所分配的 10 个字节的块丢失,并导致内存泄漏。 4) 在内存分配后忘记使用 free 进行释放最后,要避免这些内存相关的问题导致的内存越界与内存遗漏等错误,可以参考如下几点进行:
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |