Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/22.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++并发队列。p>_C++_Memory_Memory Management - Fatal编程技术网

堆栈内存未释放 我有下面的循环,它从这里的实现中弹出C++并发队列。p>

堆栈内存未释放 我有下面的循环,它从这里的实现中弹出C++并发队列。p>,c++,memory,memory-management,C++,Memory,Memory Management,我正在使用CentOS7中的系统监视器查看内存历史记录。 在从队列读取值之后,我试图释放队列占用的内存。然而,随着下面的while循环的运行,我没有看到内存使用率下降。我已经验证了队列长度确实下降了 但是,当遇到-1并且循环退出时,它确实会下降。(程序仍在运行)但我不能有这个,因为在usleep所在的地方,我想做一些密集处理 问题:为什么数据占用的内存没有释放出来?(根据系统监视器)当变量超出范围时,堆栈分配的内存不应该被释放吗 结构定义如下,并在程序开始时填充 typedef struct p

我正在使用CentOS7中的系统监视器查看内存历史记录。 在从队列读取值之后,我试图释放队列占用的内存。然而,随着下面的while循环的运行,我没有看到内存使用率下降。我已经验证了队列长度确实下降了

但是,当遇到-1并且循环退出时,它确实会下降。(程序仍在运行)但我不能有这个,因为在usleep所在的地方,我想做一些密集处理

问题:为什么数据占用的内存没有释放出来?(根据系统监视器)当变量超出范围时,堆栈分配的内存不应该被释放吗

结构定义如下,并在程序开始时填充

typedef struct pxData
{
  float value; // -1 value terminates the loop
  float x, y, z;
  std::complex<float> valueData[65536];
} pxData;
typedef结构pxData
{
浮点值;//-1值终止循环
浮动x,y,z;
std::复数值数据[65536];
}PX数据;
它填充了约10000像素的数据,大致相当于5GB。系统只有~8GB。
因此,释放内存以便在系统中进行其他处理是很重要的

这里有一些事情在起作用

虚拟内存 首先,您需要了解,仅仅因为您的程序“使用”了5GB内存,并不意味着其他程序只剩下3GB的RAM。虚拟内存意味着这5 GB可能只有1 GB的实际“驻留”数据,而其他4 GB可能实际位于磁盘上,而不是RAM中。因此,在查看程序时,查看“驻留集大小”而不是“虚拟大小”非常重要。请注意,如果您的系统实际运行的RAM不足,操作系统可能会通过“调出”一些程序的内存来缩小它们的RSS。因此,不要太担心系统监视器中出现的“5GB”——如果您有实际的、具体的性能问题,请担心

堆分配 第二个方面是为什么从队列中删除项目时虚拟大小不会减小。我们可以猜测,您通过使用
malloc
new
逐个创建这些元素,然后将它们推到队列的后面,从而将它们放入队列中。这意味着您分配的第一个元素将首先从队列中出来。这反过来意味着,当您耗尽了队列的90%时,您的内存分配可能如下所示:

[program|------------------unused-------------------|pxData]
这里的问题是,在现实世界中,仅仅因为你
免费
删除
某些东西并不意味着操作系统会立即回收这些内存。事实上,它可能无法回收任何未使用的跨度,除非它们位于“末端”(即最近分配的跨度)。因为C++没有垃圾收集,并且不能在没有你同意的情况下在内存中移动项目,所以你的程序的虚拟内存中会有这个“大洞”。该漏洞将用于满足未来的内存分配请求,但如果没有,它将一直存在,直到队列完全为空:

[program|------------------unused--------------------------]
然后,系统可以缩小虚拟地址空间:

[program]
这让你回到了起点

解决 如果要“修复”此问题,一个选项是以“反向”方式分配内存,即将最后分配的项目放在队列的前面


另一个选项是通过
mmap
为队列分配元素,例如Linux会自动为“大”的分配分配元素。您可以通过调用
M_mmap_threshold
并将其设置为略小于结构大小来更改阈值。这使得分配相互独立,因此操作系统可以单独回收它们。这种技术甚至可以应用到现有程序中,而不需要重新编译,所以如果你需要在一个程序中解决这个问题,那么C++通常是有用的。

< P>一个C++实现会调用一些<代码>操作符删除< /C> >动态释放(使用一些<代码>操作符new < /C> >内存。在几个C++标准库中,<代码>新< /Calp>调用<代码> Malc C < /C> >和<代码>删除< /代码>调用<代码>免费< /代码> .< (我关注的是Linux的观点,但原则与其他操作系统类似)

但是,虽然
malloc
(或
::operator new
)有时会通过系统调用来请求操作系统内核提供更多内存,但
free
(或
::operator delete
)通常只是将释放的内存区域标记为可供将来调用
malloc
(或
new
)使用

因此,从内核的角度来看(例如,通过
/proc/
,请参阅…),虚拟地址空间没有改变,内存仍在消耗,即使在应用程序内部它被标记为“已释放”,并将在将来的某个分配中重新使用(通过将来调用
malloc
new

和大多数C++标准都在内部使用堆数据。特别是您的本地(堆栈分配)

std::map
std::vector
(或
std::deque
)变量将调用
new
delete
,以获取内部数据


顺便说一句,我觉得你的声明很奇怪。除非每个
struct pxData
都使用了65536个
valueData
插槽,否则我建议使用一些这样的插槽

std::向量值数据;

并相应地改进代码。您可能需要执行一些
valueData.reserve(somesize)和/或
valueData.resize(somesize)和/或
值数据。向后推(somecomplexnumber)等…

什么时候超出范围
usleep
仍在范围内运行。我看不出有任何理由用
C
什么是
pop.value
?我指的是whil的下一次迭代
[program]
  std::vector<std::complex<float>> valueData;