我正在试图找出与内存模型相关的这三种问题之间的区别。
如果我想模拟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
的例子吗?
答案 0 :(得分: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 - 您可以动态分配内存并多次释放
免费后访问 - 您动态分配内存,然后在发布后释放并访问该内存。