简体   繁体   English

malloc()可能发生内存泄漏

[英]Possible memory leak with malloc()

I have this code: 我有这个代码:

#include <malloc.h>

int main()
{
    int x = 1000;

    //~600kb memory at this point
    auto m = (void**)malloc(x * sizeof(void*));
    for (int i = 0; i < x; i++)
        m[i] = malloc(x * sizeof(void*));

    for (int i = 0; i < x; i++)
        free(m[i]);

    free(m);

    //~1700kb memory at this point
    return 0;
}

When program starts memory consumption is about ~600kb, and when it ends ~1700kb. 当程序启动时,内存消耗约为~600kb,当它结束时约为1700kb。 Is it memory leak or what? 是内存泄漏还是什么?

malloc() acquires memory from the system using a variety of platform-specific methods. malloc()使用各种特定于平台的方法从系统中获取内存。 But free() does not necessarily always give memory back to the system. free()并不总是将内存返回给系统。

One reason the behavior you're seeing might exist is that when you first call malloc() it will ask the system for a "chunk" of memory, say 1 MB as a hypothetical example. 您可能存在的行为的一个原因是,当您第一次调用malloc()它会向系统询问内存的“块”,例如1 MB作为假设示例。 Subsequent calls will be fulfilled from that same 1 MB chunk until it is exhausted, then another chunk will be allocated. 后续调用将从相同的1 MB块中完成,直到它耗尽,然后将分配另一个块。

There is little reason to immediately return all allocated memory to the system just because the application is no longer using it. 没有理由立即将所有已分配的内存返回系统,因为应用程序不再使用它。 Indeed, the most likely possibilities are that (a) the application requests more memory, in which case the recently freed pieces can be doled out again, or (b) the application terminates, in which case the system can efficiently clean up all its allocated memory in a single operation. 实际上,最可能的可能性是(a)应用程序请求更多内存,在这种情况下,最近释放的部分可以再次发出,或者(b)应用程序终止,在这种情况下,系统可以有效地清理其分配的所有内容单个操作中的内存。

Is it memory leak or what? 是内存泄漏还是什么?

No. You have each malloc matching a free and if I dont miss something you have no memory leak. 不。你有每个malloc匹配free ,如果我不想念你没有内存泄漏。

Note that what you see in the process manager is the memory assigned to the process. 请注意,您在流程管理器中看到的是分配给流程的内存。 This is not necessarily equal to the memory actually in use by the process. 这不一定等于进程实际使用的内存。 The OS does not immediately reclaim it when you call free . 当您free拨打电话时,操作系统不会立即回收它。

If you have a more complex code you can use a tool like valgrind to inspect it for leaks. 如果你有一个更复杂的代码,你可以使用像valgrind这样的工具来检查它是否有泄漏。 Though, you better dont use manual memory managment at all, but use std containers instead (eg std::vector for dynamic arrays). 但是,你最好不要使用手动内存管理,而是使用std容器(例如std::vector用于动态数组)。

free() and malloc() are part of your Standard Library and their behavior is implementation dependent . free()malloc()标准库的一部分,它们的行为取决于实现 The standard does not require free() to release once acquired memory back to your Operating System. 该标准不需要free()一旦获得的内存返回到您的操作系统。

How the memory is reserved is plattform specific. 如何保留内存是特定于平台的。 On POSIX systems the mmap() and munmap() system calls can be used. 在POSIX系统上,可以使用mmap()munmap()系统调用。

Please Note that most Operating Systems implement Paging , allocating memory in chunks to processes anyway. 请注意,大多数操作系统都实现了分页 ,无论如何都要将内存分配给进程。 So releasing each single byte would only pose a performance overhead. 因此释放每个单字节只会造成性能开销。

When you are running your application under management of operating system, the process of memory allocation in languages like C/C++ is two-fold. 当您在操作系统管理下运行应用程序时,C / C ++等语言的内存分配过程是双重的。 First, there is a business of actually requesting memory to be mapped into process from operating system. 首先,有一项业务实际上要求将内存映射到操作系统的进程中。 This is done through OS-specific call, and an application needs not bothering about it. 这是通过特定于操作系统的调用完成的,应用程序无需担心它。 On Linux this call is either sbrk or mmap , depending on several factors. 在Linux上,这个调用是sbrkmmap ,具体取决于几个因素。 However, this OS-requested memory is not directly accessible to C++ code, it has no control over it. 但是,这个OS请求的内存不能直接访问C ++代码,它无法控制它。 Instead, C++ runtime manages it. 相反,C ++运行时管理它。 The second thing is actually providing a usable pointer to C/C++ code. 第二件事实际上是提供一个可用的指向C / C ++代码的指针。 This is also done by runtime when C++ code asks for it. 当C ++代码要求时,这也是由运行时完成的。

When C/C++ code calls malloc (or new ), C++ runtime first determines, if it has enough continuous memory under it's management to provide a pointer to it to application code. 当C / C ++代码调用malloc (或new )时,C ++运行时首先确定它是否在其管理下有足够的连续内存来提供指向应用程序代码的指针。 This process is further complicated by efficiency optimizations inside malloc / new , which usually provide for several allocation arenas, used depending on object sizes, but we won't talk about it. malloc / new的效率优化进一步复杂化了这个过程,它通常提供了几个分配领域,根据对象大小使用,但我们不会谈论它。 If it has, the memory region will be marked as used by application, and a pointer will be returned to the code. 如果有,则内存区域将被标记为应用程序使用,并且指针将返回到代码。

If there is no memory available, a chunk of memory would be requested from the OS. 如果没有可用内存,则会从操作系统请求一块内存。 The size of the chunk normally will be way bigger than what was requested - because requesting from OS is expensive! 块的大小通常会比请求的大 - 因为从操作系统请求是昂贵的!

When the memory is delete d/ free d, C++ runtime reclaims it. 当内存被delete d / free d,C ++运行时会回收它。 It might decide to return memory back to OS (for example, if there is a pressure in terms of total memory consumption on the machine), or it can just store it for future use. 它可能决定将内存返回给操作系统(例如,如果机器上的总内存消耗存在压力),或者它可以存储它以备将来使用。 Many times memory will never be returned to the OS until process exits, so any OS-level tool will show process consuming memory, even though the code delete 'd/ free d it all! 很多时候,在进程退出之前,内存永远不会返回到操作系统,因此任何操作系统级别的工具都会显示进程消耗内存,即使代码delete 'd / free d all all!

It is also worth noting that usually application can request memory from OS bypassing C++ runtime. 值得注意的是,通常应用程序可以通过OS绕过C ++运行时请求内存。 For example, on Linux it could be done through mmap call or, in bizarre cases, through sbrk - but in latter case you won't be able to use runtime memory management at all after this. 例如,在Linux上它可以通过mmap调用完成,或者在奇怪的情况下,通过sbrk - 但在后一种情况下,在此之后你根本无法使用运行时内存管理。 If you use those mechanisms, you will immediately see process memory consumption growing or decreasing with every memory request or return. 如果使用这些机制,您将立即看到进程内存消耗随着每个内存请求或返回而增长或减少。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM