这基本上就是问题。如果我有一个指针int *a = &someIntVar
并且我不在程序过程中删除它,它会在程序终止后留在内存中吗?这是数据碎片的情况吗?
修改
我错误地使用了一个糟糕的例子。所以int *a = new int[100];
永远不会被删除,即使它被删除,答案也会删除指针,而不是指针。然而指针也有一个长度。所以问题是,在Windows或Linux操作系统上,它会在指针后自动清理吗? (假设C ++)
答案 0 :(得分:4)
由于你没有new
这个指针,你没有泄漏内存。
如果你要int* a = new int;
而不是delete a
,那么你会泄漏a
。
根据经验,new
的数量应等于delete
的数量。
当someIntVar
超出范围时,堆栈被解开并且其内存将被释放,当然a
将悬空。
答案 1 :(得分:4)
不,当进程终止时,通常会释放进程分配的所有内存。但是对于文件句柄或图形资源(例如在Win32设备上下文句柄,位图等)中的情况可能并非如此。
答案 2 :(得分:1)
关于delete p
的一个令人困惑的事实是,它实际上并未删除p
,而是*p
。也就是说,你不删除指针,而是删除指针。每当您看到delete
时,都应将其视为delete_what_is_pointed_to_by
。哦是的,只有delete
你new
。
答案 3 :(得分:1)
没有正确删除指针片段内存?
否。大量内存分配和释放会破坏内存。
这是对内存分配的直观解释(它比这更复杂,我的例子充其量是天真的,忽略了很多问题,但它应该为你提供一些想法)。
内存分配通常发生在(至少)两个步骤中:
操作系统为应用程序分配内存块。
应用程序从可用块中分配内存供自己使用。
如果应用程序使用了所有可用内存(或者它不能再分配),操作系统将为应用程序分配更多内存。这是透明地完成应用程序,但它需要时间(这就是内存分配缓慢的原因)。
当应用程序释放内存时,地址/块被标记为空闲,并将在应用程序的后续分配请求(new / malloc / realloc / etc)上重用。
当分配给应用程序的内存块变得碎片化时(某些片段被分配,一些片段空闲),就会发生内存碎片。
例如:
int *a = new int;
int *b = new int;
int *c = new int;
int *d = new int;
int *e = new int;
int *f = new int;
// if the memory blocks for the pointers were allocated contiguously,
// the heap will look like this:
// [ a ][ b ][ c ][ d ][ e ][ f ][ free memory ... ]
// sometime later:
delete b;
delete d;
delete e;
// same memory block will look like this:
// [ a ][free][ c ][free][free][ f ][ free memory ... ]
为简单起见,假设您的应用程序以1000字节可用内存开头。如果在第一步中分配了200 int*
(200个不同的变量),则分配200 x 4 = 800字节,200字节空闲。
如果你想分配(第二步)new int[100]
更多(一个指针,400多个字节),你将没有足够的可用内存,应用程序将不得不从操作系统请求更多。在当前块中至少需要200个字节,或者从操作系统中至少需要400个字节的新块。
如果删除了在步骤1中分配的内存以在步骤2中分配空间,那么删除的内存将至关重要:
如果您删除了最后分配的指针 - 您需要删除最后50个指针(50x4 = 200) - 您需要释放200个字节+ 200个未分配的指针= 400个需要)。的确定
如果你删除了在步骤1中分配的每个第二个指针(或前50个指针)你有400个字节可用,但是碎片并且没有400个字节的连续内存可用。由于内存碎片,您在步骤2中的分配将失败。
我错误地使用了一个糟糕的例子。所以
int *a = new int[100];
永远不会被删除,即使它被删除,答案也会删除指针,而不是指针。然而指针也有一定的长度。
当你有int *a = new int[100];
时,你有两个部分:
a
(指针本身)的内存是4个字节(假设32位架构)在堆栈上分配。
a
指向的内存为400字节,在堆上分配。
当您致电delete[]a;
时,将释放堆内存。当*超出范围时,堆栈存储器(用于指针本身)将被释放到可用的堆栈空间。
您只需关注删除堆内存即可。根据程序本身的需要释放/重用堆栈存储器。
答案 4 :(得分:1)
int *a = new int[100];
之后你使用sizeof(a) + sizeof(int[100])
字节的内存。在delete a
之后,您仍在使用sizeof(a)
字节的内存。这是合乎逻辑的:您可以接下来写a = new int[50];
。 a
的内存仅在a
本身超出范围时才会释放。如果a
是全局的,那将是程序终止。
答案 5 :(得分:0)
在您使用的任何操作系统上试试这个:
作为附注,不要假设如果你做删除[] p;在代码中间,您的100k * 4立即返回系统。这可能是也可能不是 - 例如Linux有自己的内存管理器来做出这样的决定。
Arpan