Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/147.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 不正确删除指针碎片内存?_C++_Memory Leaks - Fatal编程技术网

C++ 不正确删除指针碎片内存?

C++ 不正确删除指针碎片内存?,c++,memory-leaks,C++,Memory Leaks,这基本上就是问题所在。如果我有一个指针int*a=&someIntVar,并且我没有在程序运行过程中删除它,那么在程序终止后它会留在内存中吗?这是数据碎片的情况吗 编辑: 我的错误是使用了一个坏的例子。所以int*a=新的int[100]永远不会被删除,即使它被删除了,答案是删除了指针对象,而不是指针。然而指针也有长度。所以问题是,在Windows或Linux操作系统上,指针之后是否会自动清理?(假设是C++)因为您没有新建这个指针,所以您没有泄漏内存 你要做的是int*a=newint而不是删

这基本上就是问题所在。如果我有一个指针
int*a=&someIntVar
,并且我没有在程序运行过程中删除它,那么在程序终止后它会留在内存中吗?这是数据碎片的情况吗

编辑:


我的错误是使用了一个坏的例子。所以
int*a=新的int[100]
永远不会被删除,即使它被删除了,答案是删除了指针对象,而不是指针。然而指针也有长度。所以问题是,在Windows或Linux操作系统上,指针之后是否会自动清理?(假设是C++)

因为您没有
新建
这个指针,所以您没有泄漏内存

你要做的是
int*a=newint
而不是
删除一个
,那么你就会泄漏
一个

根据经验法则,
new
s的数量应等于
delete
s的数量


someIntVar
超出范围时,堆栈将展开,其内存将被释放,
a
当然将悬空。

否,进程终止时,通常会释放进程分配的所有内存。但是像文件句柄或图形资源(即Win32设备上下文句柄、位图等)这样的东西可能不是这样。

关于
delete p
的一个令人困惑的事实是,它实际上并没有删除
p
,而是删除
*p
。也就是说,您不删除指针,而是删除指针对象。无论何时看到
delete
,您都应该将其视为
delete\u被
指向的对象。哦,是的,只有
删除
你的
新的

不正确删除指针碎片内存

否。大量内存分配和释放将导致内存碎片

下面是对内存分配的直观解释(它比这更复杂,我的示例充其量也很幼稚,忽略了很多问题,但它应该能为您提供一些想法)

内存分配通常(至少)分两步进行:

  • 操作系统为应用程序分配内存块

  • 应用程序从可用块中分配内存供自己使用

  • 如果应用程序使用了所有可用内存(或者无法再分配),操作系统将为应用程序分配更多内存。这对应用程序来说是透明的,但需要时间(这就是内存分配缓慢的原因)

    当应用程序释放内存时,地址/块被标记为空闲,并将由应用程序在后续分配请求(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字节空闲

    如果您想分配(在第二步中)
    newint[100]
    more(一个指针,400多个字节),您将没有足够的可用内存,应用程序将不得不从操作系统请求更多。当前块中至少还需要200个字节,或者操作系统中至少需要400个字节的新块)

    如果您删除了步骤1中分配的内存,以便为步骤2中的分配腾出空间,则删除的内存至关重要:

    • 如果您删除了最后分配的指针-您需要删除最后50个指针(50x4=200)-您将释放200个字节+200个未定位指针(需要400个)正常

    • 如果您删除在步骤1中分配的每2个指针(或前50个指针),您将有400个字节可用,但零碎并且没有400个字节的连续内存可用。由于内存碎片,您在步骤2中的分配将失败

    我的错误是使用了一个坏的例子。所以
    int*a=新的int[100]
    永远不会被删除,即使它被删除了,答案是删除了指针对象,而不是指针。然而指针也有长度

    当你有
    int*a=newint[100]这里有两个部分:

    • a
      (指针本身)的内存为堆栈上分配的4个字节(假设为32位体系结构)

    • a
      指向的内存是400字节,在堆上分配

    当您调用
    delete[]a时,堆内存将被释放。当*超出范围时,堆栈内存(指针本身)将释放到可用堆栈空间


    您只需要关心删除堆内存。堆栈内存由程序本身根据需要释放/重新使用。

    在您使用的任何操作系统上尝试以下操作:

  • 首先观察进程内存占用情况。在Linux中使用top,在Windows中使用任务管理器
  • 分配一个100000的内存,如int*p=newint[100000]
  • 观察进程的内存占用情况。它必须至少增加100k*4字节。现在查看为其他进程保留的“空闲”内存
  • 让程序运行,不要删除任何内容。执行后,空间被返回到系统——您应该看到其他程序中使用的可用内存现在增加了
  • 作为旁注,不要假设如果您执行delete[]p;在代码的中间,你的100K * 4立即返回系统。这可能是真的,也可能不是真的——例如,Linux有自己的内存管理器来做出这样的决定


    Arpan在
    int*a=newint[100]之后
    您正在使用
    sizeof(a)+sizeof(int[100])
    字节内存。在
    删除一个
    后,您仍在使用<