内存泄漏,访问释放内存和双重免费有什么区别?

时间:2017-11-28 14:04:29

标签: c++ memory memory-management memory-leaks

我正在试图找出与内存模型相关的这三种问题之间的区别。

如果我想模拟memory leak场景,我可以在不调用相应删除方法的情况下创建指针。

int main() {
    // OK
    int * p = new int;
    delete p; 

    // Memory leak
    int * q = new int;
    // no delete
}

如果我想模拟一个double free场景,我可以释放一个指针两次,这部分内存将被分配两次。

a = malloc(10);     // 0xa04010
b = malloc(10);     // 0xa04030
c = malloc(10);     // 0xa04050

free(a);
free(b);  // To bypass "double free or corruption (fasttop)" check
free(a);  // Double Free !!

d = malloc(10);     // 0xa04010
e = malloc(10);     // 0xa04030
f = malloc(10);     // 0xa04010   - Same as 'd' !

但是,我不知道accessing freed memory是什么。任何人都可以给我一个accessing freed memory的例子吗?

4 个答案:

答案 0 :(得分:4)

  1. 内存泄漏很糟糕。
  2. 双重自由更糟糕。
  3. 访问已释放的内存更糟
  4. 内存泄漏

    这不是错误本身。泄漏计划仍然有效。这可能不是问题。但这仍然很糟糕;随着时间的推移,您的程序将保留主机的内存,而不会释放它。如果在程序完成之前主机的内存已满,则会遇到麻烦。

    双重释放

    根据标准,这是未定义的行为。实际上,这几乎总是由C ++运行时调用std::abort()

    访问释放的内存

    还有未定义的行为。但在某些情况下,不会发生任何不好的事情。您将测试您的程序,将其投入生产。有一天,没有明显的理由,它会打破。并且会随意打破:重写简历的最佳时间。

    这是如何访问释放的内存:

    // dont do this at home
    int* n = new int{};
    delete n;
    std::cout << *n << "\n"; // UNDEFINED BEHAVIOUR. DONT.
    

答案 1 :(得分:3)

您的内存泄漏示例(分配内存但释放它)和双重释放(将指定内存的指针多次传递给free / delete)是正确的。

执行双重释放并不意味着malloc将按照示例所示多次返回一段内存。它的作用是调用undefined behavior,这意味着你的程序行为无法预测。

访问免费内存意味着释放指针,然后尝试使用它:

int *a = malloc(10 * sizeof(int));     // allocate memory
free(a);                               // free memory
print("a[0]=%d\n", a[0]);              // illegal: use after free

答案 2 :(得分:2)

你是正确的内存泄漏和双重免费。当您取消引用已释放的指针时,会访问释放的内存:

int *ptr = malloc(sizeof(int));
*ptr = 123;
free(ptr);
int invalid = *ptr; // Accessing freed memory

这样的问题很难被发现,因为程序在一段时间内仍然按预期工作。如果您希望稍后重用指针变量,最好在调用NULL后立即分配free。这样,后续的取消引用会很快失败。

答案 3 :(得分:1)

  

我正在试图找出与内存模型相关的这三种问题之间的区别。

  • 内存泄漏 - 您动态分配内存并永不释放内存。

  • double free - 您可以动态分配内存并多次释放

  • 免费后访问 - 您动态分配内存,然后在发布后释放并访问该内存。