Memory leaks 什么是内存泄漏?

Memory leaks 什么是内存泄漏?,memory-leaks,Memory Leaks,很明显,我有很多关于这个话题的信息,但我想确保我能理解。从我可以看出,理解堆栈/堆的关系对于真正理解内存泄漏很重要 这就是我所理解的。欢迎改正 当您第一次启动程序时,会分配一块内存,比如0x000到0xFFF。第一部分(比如0x000到0x011)是加载程序代码的代码/文本段 +--------------+ 0x011 | Program Code | +--------------+ 0x000 然后您就有了保存局部变量的堆栈(比如0x012到0x7ff),它们被存储/检索为FIFO。如果

很明显,我有很多关于这个话题的信息,但我想确保我能理解。从我可以看出,理解堆栈/堆的关系对于真正理解内存泄漏很重要

这就是我所理解的。欢迎改正

当您第一次启动程序时,会分配一块内存,比如0x000到0xFFF。第一部分(比如0x000到0x011)是加载程序代码的代码/文本段

+--------------+ 0x011
| Program Code |
+--------------+ 0x000
然后您就有了保存局部变量的堆栈(比如0x012到0x7ff),它们被存储/检索为FIFO。如果你有

char middleLetter(string word){
     int len = word.length();
     return word[len/2];
}

int main(){
   int cool_number;
   char letter;
   letter = middleLetter("Words");
   ...
然后在堆栈上分配变量,如下所示:

+-------------+ 0x7ff
|             |
|             |
|             |
| ...         |
| len         |
| letter      |
| cool_number |
+-------------+ 0x012
当然,如果您在某处分配内存(使用
malloc
new
),但从未释放内存,那么您的堆可能是这样的,并且您现在有内存泄漏:

+-------------+ 0xfff
|             |
| malloc(20)  | 0xf64
| malloc(50)  | 0xf32
| malloc(50)  | 0xf00
| ...         |
|             |
+-------------+ 0x800
int main(void) {
    void *some_memory = malloc(400);

    // rest of program...
    // some_memory is never freed
}
这意味着,虽然您可以使用指针算法直接访问0xf32,但操作系统/您的程序认为内存位置0xf00-0xf46已经被占用,并且在关闭程序并释放内存之前,不会再次使用这些位置进行存储。但是共享内存呢?维基百科说它永远不会被发布(直到你的电脑重新启动?)。你怎么知道它是不是共享内存


这是一个相当好的基本理解吗?我有什么遗漏/错了吗?谢谢你的关注

这样想吧。当使用需要程序员管理内存的语言进行开发时,您需要为程序将使用的每个对象显式地分配和销毁内存。当你不能正确地创建一些东西时,你很容易知道,因为你的程序不能工作。如果没有正确地销毁对象(这称为内存泄漏),则查找和调试这种情况要困难得多


让我们看一个典型的应用程序,比如RSS新闻阅读器。在这样的应用程序中,通常有许多循环(通过不同的RSS提要、不同的RSS项、RSS标记等进行循环)。如果您有一个实例,其中创建的对象没有被正确销毁(或释放),那么每次运行“泄漏”代码时,您都会在内存中遇到另一个废弃的对象。如果循环运行1000次,将有1000个废弃对象占用空间。您可以看到这是如何快速累积起来消耗宝贵资源的。

通常,函数(子例程)中的自动变量也将存储在堆栈上。只有“malloc”或“new”数据分配来自堆。接下来,可以在程序结束之前释放和重用(多次)基于堆的分配。分配系统跟踪正在使用的区域和释放的区域。最后,内存泄漏是指您的程序在没有释放内存的情况下丢失了一些已分配的内存。这可以通过使用新值写入指针或将指针存储在具有有限生存期/作用域的变量中来实现

函数变量通常也在堆栈上,而不是堆上。在大多数系统中,堆用于动态分配。通常的内存泄漏情况是

  • 调用函数F
  • F分配(新的或malloc)一些内存
  • F返回调用方(无删除/释放)
  • 指向动态分配内存的指针超出范围
    • 内存仍然被分配
    • 你不能再删除/释放它了

  • 看起来您确实理解了它——只有一个例外:在您的示例中,len和其他变量一样是堆栈变量
    new
    malloc
    在堆上创建,其他所有内容(局部变量等)都在堆栈上。main的局部变量与任何其他函数的变量都没有区别


    共享内存是一种非常罕见的情况,通常不需要它,因此除非明确地请求它,否则它将不具有它(否则,一些随机的其他进程可能会使用与进程使用的内存非常相同的东西-显然,这会严重破坏事物)。

    < P>看起来,您使用的是C++代码。在C++中,局部变量放在栈上(我猜全局变量也是,但我不确定)。因此,middletter函数中的len也会放在调用堆栈上。我建议阅读这篇文章:

    将新运算符与类型一起使用时,如
    int*x=newint
    
    如果继续这样做,最终会耗尽堆上可分配给的空间,您的程序将越来越接近崩溃,因为它没有内存可处理,还有其他问题。

    内存泄漏变得很简单。每当您使用malloc/new分配内存,并且在使用完该内存后不使用free/delete解除分配内存时。。。将导致内存泄漏!分配的内存将保留在那里,程序将不再使用该空间


    当泄漏发生在多次调用的函数上时,这是一个严重的问题,使得每次调用该函数时泄漏变得越来越大。

    在垃圾收集系统中,“内存泄漏”一词有时看起来有点模糊。我将提供以下定义,它与使用显式释放的系统一样适用于垃圾收集系统: 如果存在初始输入序列S和重复输入模式P,则程序或子程序P存在内存泄漏,例如:

  • 输入程序或子程序输入S后加上P将使程序保持相同的状态”
    int main(void) {
        void *some_memory = malloc(400);
    
        // rest of program...
        free(some_memory);
    }