C语言动态内存分配(中)内存错误和泄漏

前言

上篇文章《C语言动态内存分配(上)函数介绍》介绍了malloc()和free()函数的使用,在程序中使用动态内存分配是会出现很多错误的。比如对nullptr指针进行访问,指针指向的值超过了分配的范围,释放了不是动态分配的地址,使用已经释放的内存空间。

访问没有分配的内存

动态内存分配最容易出现的错误就是使用没有分配的内存。

#include 
#include 

#define malloc              DO NOT CALL malloc DIRECTLY!
#define MALLOC(num, type)   (type*)alloc((num) * sizeof(type))
#undef malloc

void* alloc(size_t size) {
    void * new_mem;

    new_mem = malloc(size);
    if (new_mem == nullptr) {
        LOG(INFO) << "Out of memory!";
        exit(EXIT_FAILURE);
    }
    return new_mem;
}

int main(int argc, char* argv[]) {
    int* new_memory;
    // Get space for a bunch of integers
    new_memory = MALLOC(25, int);
    return 0;
}

上述代码定义了一个宏MALLOC对官方malloc进行封装,对是否为nullptr进行强制检查,同时禁用官方的malloc()函数。

访问越界

第二容易出现的错误就是访问内存越界,比如创建25个整形,通过小于0或者大于24的下标访问就会越界。如果改变它们就会销毁存在这里的任何东西,这种问题很难被发现。

当程序使用动态分配内存失败后,容易将问题归咎于malloc()和free()函数上,但是它们很少出错,问题的根本来源经常是因为访问内存越界。

访问释放的内存

不能访问已经被free()函数释放的内存,它看上去可能是显而易见的,不会访问释放的内存。但是有时候会存在多个指针指向同一块内存,它们分布于程序的不同位置,很难确保在释放后其它的指针都没有访问该片内存,也就是说,你在释放内存前,需要保证所有的指针都已经完成相关的操作。

内存泄漏

在使用free()的时候会发生错误,传递给free()函数的地址必须是通过malloc(), calloc()或者realloc()函数获取的,不正确的释放会导致程序崩溃。相似的问题还有仅仅释放部分内存,下面的代码释放后面5个整形内存

// get 10 integers
int* pi = static_cast(malloc(10 * sizeof(int)));
// Free only the last 5 integers; keep the first 5.
free(pi + 5);

释放部分内存是不允许的,整个内存必须全部释放。如果需要释放部分内存,可以通过realloc函数分配更小的内存空间,后续的内存被释放,这样更有效率。

在不需要内存时,应该被释放,这片空间可以被后续使用。分配内存但是没有释放它,会导致内存泄漏。内存泄漏会消耗计算机有限的资源,直到最终耗尽,重启是唯一能够恢复的办法。

内存泄漏

有些操作系统会记录给每个程序使用的内存,当程序退出后,所有的内存都会被释放。即使这样,内存泄漏仍然是个严重的问题,因为程序可以持续分配内存直到内存耗尽,此时程序无法正常工作,可能导致当前的任务丢失。

发表评论
留言与评论(共有 0 条评论) “”
   
验证码:

相关文章

推荐文章