- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
是的,这可能是您第三次看到此代码,因为我还问了另外两个问题(this和this)。
代码很简单:
#include <vector>
int main() {
std::vector<int> v;
}
g++ test.cc && valgrind ./a.out
==8511== Memcheck, a memory error detector
...
==8511== HEAP SUMMARY:
==8511== in use at exit: 72,704 bytes in 1 blocks
==8511== total heap usage: 1 allocs, 0 frees, 72,704 bytes allocated
==8511==
==8511== LEAK SUMMARY:
==8511== definitely lost: 0 bytes in 0 blocks
==8511== indirectly lost: 0 bytes in 0 blocks
==8511== possibly lost: 0 bytes in 0 blocks
==8511== still reachable: 72,704 bytes in 1 blocks
==8511== suppressed: 0 bytes in 0 blocks
...
==8511== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
a.out
已经终止,所以没有其他进程正在维护此内存缓存-还是有一个?
a.out
(静态库,
.a
),要么被调用在
.so
的过程中(共享对象
a.out
)运行时。
最佳答案
澄清度
首先,进行一些澄清。您问:...我的程序a.out已经终止,没有其他进程正在维护此内存缓存-还是有一个?
我们所讨论的一切都在单个进程的生存期内:该进程退出时始终返回所有分配的内存。没有比进程1持久的缓存。即使没有运行时分配器的任何帮助,也将返回内存:进程终止时,操作系统仅“收回”该内存。因此,正常分配的终止应用程序不会发生系统范围的泄漏。
现在,Valgrind报告的是进程终止时但操作系统清理所有内容之前正在使用的内存。它在运行时库级别而不是操作系统级别工作。因此,它的意思是“嘿,当程序完成时,还有72,000个字节尚未返回到运行时”,但未说明的含义是“这些分配将很快由OS清除”。
基本问题
所示的代码和Valgrind输出与名义问题并没有很好的关联,因此让我们将它们分开。首先,我们将尝试回答您有关分配器的问题:它们为什么存在以及为什么它们通常不立即将释放的内存返回给OS,而忽略了该示例。
你问:
1) Why keep them in an internal cache? If it is for speed, how is it faster? Yes, the OS needs to maintain a data structure to keep track of memory allocation, but this the maintainer of this cache also needs to do so.
brk
,它只能增加或减少一个连续的内存块-您无法“释放”任意较早的分配。它们还提供了mmap
,它允许您独立分配和释放内存块,但是它们以PAGE_SIZE
粒度(在Linux上为4096字节)进行分配。因此,如果您希望请求32个字节,那么如果您没有自己的分配器,则必须浪费4096 - 32 == 4064
字节。在这些操作系统上,您实际上需要一个单独的内存分配运行时,它将这些粗粒度的工具转换为能够有效分配小块的东西。HeapAlloc
调用,它是“OS”的一部分,确实提供类似于malloc
的功能,用于分配和释放任意大小的内存块。然后,对于某些编译器而言,malloc
只是作为HeapAlloc
的一个薄包装而实现的(此调用的性能在最近的Windows版本中已大大改善,这使其可行)。尽管如此,尽管HeapAlloc
是操作系统的一部分,但它并未在内核中实现-它也大多在用户模式库中实现,可管理可用和已用块的列表,并偶尔会进行内核调用以从内存中获取大块内存。核心。因此,它主要是另一种伪装形式的malloc
,它所保留的任何内存也无法用于任何其他进程。 malloc
分配或免费分配通常只有十几条指令,并且可能在10 ns或更短的时间内完成。最重要的是,系统调用不能“信任他们的输入”,因此必须仔细验证从用户空间传递的参数。在free
的情况下,这意味着要检查用户是否传递了有效的指针!大多数运行时free
仅实现崩溃或无提示地破坏内存,因为没有责任保护进程免受自身侵害。 new
,malloc
和friends是该语言定义的一部分。然后,将它们作为实现其余语言的运行时的一部分实现,而不是与大多数与语言无关的OS完全自然地实现。例如,该语言可能对各种对象具有特定的对齐要求,最好由语言感知分配器来处理。对语言或编译器的更改也可能意味着必须对分配例程进行更改,并且希望更新内核以适应您的语言功能将是一个艰难的要求! malloc
实现都是如此。首先,请注意,这本身并不是泄漏-未分配的内存仍可用于分配它的进程,即使不是其他进程也是如此。
brk
和sbrk
system calls,返回释放的内存根本不可行,除非它恰好位于从brk
或sbrk
分配的最后一个块的末尾。这是因为这些调用提供的抽象是一个大的连续区域,您只能从一端延伸。您不能从内存中途交出内存。大多数分配器都没有理会这种不寻常的情况,即所有释放的内存恰好在brk
区域的末尾。mmap
调用更加灵活(此讨论通常也适用于VirtualAlloc
与mmap
等效的Windows),允许您至少以页面粒度返回内存-但这很难!在释放属于该页面的所有分配之前,您无法返回页面。取决于应用程序的大小和分配/免费模式,可能是常见的还是不常见的。它适用于大型分配的情况-大于一页。在这里,如果通过mmap
完成分配,则可以保证释放大部分分配,实际上,某些现代分配器可以直接从mmap
满足大型分配,并使用munmap
将它们分配回操作系统。对于glibc
(以及扩展的C++分配运算符),您甚至可以控制this threshold:M_MMAP_THRESHOLD
For allocations greater than or equal to the limit specified
(in bytes) by M_MMAP_THRESHOLD that can't be satisfied from
the free list, the memory-allocation functions employ mmap(2)
instead of increasing the program break using sbrk(2).
Allocating memory using mmap(2) has the significant advantage
that the allocated memory blocks can always be independently
released back to the system. (By contrast, the heap can be
trimmed only if memory is freed at the top end.) On the other
hand, there are some disadvantages to the use of mmap(2):
deallocated space is not placed on the free list for reuse by
later allocations; memory may be wasted because mmap(2)
allocations must be page-aligned; and the kernel must perform
the expensive task of zeroing out memory allocated via
mmap(2). Balancing these factors leads to a default setting
of 128*1024 for the M_MMAP_THRESHOLD parameter.
munmap
(可能通过brk
缩小)强加的TLB刷新。 malloc_trim
。 madvise(..., MADV_DONTNEED)
调用,告诉操作系统“该范围没有任何用处,您不必保留其范围。交换中的内容”。它仍然保留在进程中映射的虚拟地址空间,并且以后可用(零填充),因此它比munmap
和后续的mmap
效率更高,但它避免了无意义地将释放的内存区域交换为swap.2 vector<int>
进行的测试实际上并未测试任何内容,因为只要您使用了最低限度的优化级别,一个空的,未使用的
std::vector<int> v
甚至都不会使用
create the vector object。即使没有优化,也不会发生分配,因为大多数
vector
实现都是在第一次插入时分配的,而不是在构造函数中的。最后,即使您使用的是一些不常见的编译器或库来进行分配,它也会占用很少的字节,而不是Valgrind报告的〜72,000字节。
#include <vector>
volatile vector<int> *sink;
int main() {
std::vector<int> v(12345678);
sink = &v;
}
MADV_FREE
,它的语义似乎与
MADV_DONTNEED
相似。
关于c++ - 为什么内存分配器不主动将释放的内存返回给操作系统?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45538993/
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
在编码时,我问了自己这个问题: 这样更快吗: if(false) return true; else return false; 比这个? if(false) return true; return
如何在逻辑条件下进行“返回”? 在这样的情况下这会很有用 checkConfig() || return false; var iNeedThis=doSomething() || return fa
这是我的正则表达式 demo 如问题所述: 如果第一个数字是 1 则返回 1 但如果是 145 则返回 145 但如果是 133 则返回 133 样本数据a: K'8134567 K'81345678
在代码高尔夫问答部分查看谜题和答案时,我遇到了 this solution返回 1 的最长和最晦涩的方法 引用答案, int foo(void) { return! 0; } int bar(
我想在下面返回 JSON。 { "name": "jackie" } postman 给我错误。说明 Unexpected 'n' 这里是 Spring Boot 的新手。 1日龄。有没有正确的方法来
只要“is”返回 True,“==”不应该返回 True 吗? In [101]: np.NAN is np.nan is np.NaN Out[101]: True In [102]: np.NAN
我需要获取所有在 6 号或 7 号房间或根本不在任何房间的学生的详细信息。如果他们在其他房间,简单地说,我不希望有那个记录。 我的架构是: students(roll_no, name,class,.
我有一个表单,我将它发送到 php 以通过 ajax 插入到 mysql 数据库中。一切顺利,php 返回 "true" 值,但在 ajax 中它显示 false 消息。 在这里你可以查看php代码:
我在 Kotlin 中遇到了一个非常奇怪的无法解释的值比较问题,以下代码打印 假 data class Foo ( val a: Byte ) fun main() { val NUM
请注意,这并非特定于 Protractor。问题在于 Angular 2 的内置 Testability service Protractor 碰巧使用。 Protractor 调用 Testabil
在调试窗口中,以下表达式均返回 1。 Application.WorksheetFunction.CountA(Cells(4 + (i - 1) * rows_per_record, 28) & "
我在本地使用 jsonplaceholder ( http://jsonplaceholder.typicode.com/)。我正在通过 extjs rest 代理测试我的 GET 和 POST 调用
这是 Postman 为成功调用我的页面而提供的(修改后的)代码段。 var client = new RestClient("http://sub.example.com/wp-json/wp/v2
这个问题在这里已经有了答案: What to do with mysqli problems? Errors like mysqli_fetch_array(): Argument #1 must
我想我对 C 命令行参数有点生疏。我查看了我的一些旧代码,但无论这个版本是什么,都会出现段错误。 运行方式是 ./foo -n num(其中 num 是用户在命令行中输入的数字) 但不知何故它不起作用
我已经编写了一个类来处理命名管道连接,如果我创建了一个实例,关闭它,然后尝试创建另一个实例,调用 CreateFile() 返回 INVALID_HANDLE_VALUE,并且 GetLastErro
即使 is_writable() 返回 true,我也无法写入文件。当然,该文件存在并且显然是可读的。这是代码: $file = "data"; echo file_get_contents($fil
下面代码中的变量 $response 为 NULL,尽管它应该是 SOAP 请求的值。 (潮汐列表)。当我调用 $client->__getLastResponse() 时,我从 SOAP 服务获得了
我一直在网上的不同论坛上搜索答案,但似乎没有与我的情况相符的... 我正在使用 Windows 7,VS2010。 我有一个使用定时器来调用任务栏刷新功能的应用程序。在该任务栏函数中包含对 LoadI
我是一名优秀的程序员,十分优秀!