有一些我不理解的东西,我非常感谢一些澄清。我知道有很多关于std :: containers和内存没有被释放,但我仍然不明白一个特定的事实。
下面是一个最小程序,它代表了我在生产系统中遇到的问题。在注释中,在等待Ubuntu上的std :: cin时,从/ proc / PROC_NUM / status读取内存消耗。问题也在评论中。
#include <iostream>
#include <stdlib.h>
#include <fstream>
#include <vector>
class MyObject
{
public:
MyObject(int r=1000)
: array(new float[r])
{
for (int i = 0; i<r;i++)
{
array[i] = random();
}
}
~MyObject()
{
delete[] array;
}
public:
float* array;
};
int main(int argc,char*argv[])
{
char a;
const int count=100;
std::cout<<"Start after input"<<std::endl;
std::cin >> a;
// VmSize: 12704 kB
{
std::vector<MyObject*> vec;
for(int i=0; i<count; i++)
{
vec.push_back(new MyObject);
}
std::cout<<"Release after input"<<std::endl;
std::cin >> a;
// VmSize: 13100 kB, alright, MyObjects fill around 400kB (what I expected)
for (int i=0; i<count; i++)
{
delete vec[i];
vec[i]=NULL;
}
std::cout<<"Run out of scope of vector after input"<<std::endl;
std::cin >> a;
// VmSize: 13096 kB, Why are the 400k not freed yet?
}
std::cout<<"Shutdown after input"<<std::endl;
std::cin >> a;
// VmSize: 12704 kB, Why are now around 400k freed? The only thing that is freed here is the vector of pointers.
return 0;
}
如果我改为使用MyObjects数组,删除后会立即释放内存:
#include <iostream>
#include <stdlib.h>
#include <fstream>
#include <vector>
class MyObject
{
public:
MyObject(int r=1000)
: array(new float[r])
{
for (int i = 0; i<r;i++)
{
array[i] = random();
}
}
~MyObject()
{
delete[] array;
}
public:
float* array;
};
int main(int argc,char*argv[])
{
char a;
const int count=100;
std::cout<<"Start after input"<<std::endl;
std::cin >> a;
// VmSize: 12700 kB
{
MyObject* vec(new MyObject[count]);
std::cout<<"Release after input"<<std::endl;
std::cin >> a;
// VmSize: 13096 kB, alright, around 400k again
delete[] vec;
std::cout<<"Run out of scope of vector after input"<<std::endl;
std::cin >> a;
// VmSize: 12700 kB, 400k freed again, perfect.
}
std::cout<<"Shutdown after input"<<std::endl;
std::cin >> a;
// VmSize: 12700 kB, nothing changed, as expected
return 0;
}
我读到的答案告诉我不能相信操作系统的内存号码(目前我在Linux上使用了/ prop / PROC_NO / status的输出)。我可以使用什么来监控内存消耗?我在XCode Instruments的Mac上试过同样的东西,我甚至没有那个问题。第一种情况下的含义内存消耗等于第二种情况。
在Ubuntu上,我尝试了不同版本的gcc和clang,它们都表现出相同的行为。
在我的高效系统中,有一个std :: map而不是std :: vector,但问题是一样的。
答案 0 :(得分:3)
VMSize与范围语言中范围的输入和离开几乎没有关系(存在那些没有范围的编程环境?)。
VMSize反映了操作系统实际必须使用哪个内存来满足程序的内存要求。例如,如果使用malloc
,new[]
或匿名mmap
分配大块内存,则地址空间仅保留,但不会被占用,因此不会显示在VMSize中。
此外,大多数运行时库分配大量存储器中的内存,而对象分配则是来自这些大型存储器的片段;在释放对象之后,只有块中的空格被标记为空闲,并且可以在下一次分配时被回收。如果释放从中分配的所有对象并且没有其他对象驻留在其中,则释放如此大量内存的典型提示。所以你的std :: vector和你手动分配的对象很可能是从同一个Hunk分配的,并且std :: vector实例可以防止它被返回到系统。 但这只是猜想!详细信息取决于所使用的C ++运行时库。
答案 1 :(得分:0)
在第一个示例中,您在范围内的堆栈上创建了向量。您可能知道C ++有RAII http://en.cppreference.com/w/cpp/language/raii来自动进行资源管理,当您离开范围内存保留给vector时,将被释放。这就是为什么你在你的例子结尾再次看到VmSize:12704的原因!
如果您不在堆栈上创建向量,则第一个示例的行为将与预期的一样。
#include <iostream>
#include <stdlib.h>
#include <fstream>
#include <vector>
#include "stdlib.h"
#include "stdio.h"
#include "string.h"
int parseLine(char* line){
int i = strlen(line);
while (*line < '0' || *line > '9') line++;
line[i-3] = '\0';
i = atoi(line);
return i;
}
int getValue(){ //Note: this value is in KB!
FILE* file = fopen("/proc/self/status", "r");
int result = -1;
char line[128];
while (fgets(line, 128, file) != NULL){
if (strncmp(line, "VmSize:", 7) == 0){
result = parseLine(line);
break;
}
}
fclose(file);
return result;
}
class MyObject
{
public:
MyObject(int r=1000)
: array(new float[r])
{
for (int i = 0; i<r;i++)
{
array[i] = random();
}
}
~MyObject()
{
delete[] array;
}
public:
float* array;
};
int main(int argc,char*argv[])
{
const int count=100;
// VmSize: 12704 kB
std::cout << "VmSize: " << getValue() << std::endl;
{
std::vector<MyObject*> *vec = new std::vector<MyObject*>();
for(int i=0; i<count; i++)
{
vec->push_back(new MyObject);
}
// VmSize: 13100 kB, alright, MyObjects fill around 400kB (what I expected)
std::cout << "VmSize: " << getValue() << std::endl;
for (int i=0; i<count; i++)
{
delete (*vec)[i];
(*vec)[i]=NULL;
}
//Now we deallocating memory! In case of stack it will be done automatically when we left the scope.
delete vec;
std::cout << "VmSize: " << getValue() << std::endl;
// VmSize: 13096 kB, Why are the 400k not freed yet?
}
std::cout << "VmSize: " << getValue() << std::endl;
// VmSize: 12704 kB, Why are now around 400k freed? The only thing that is freed here is the vector of pointers.
return 0;
}
答案 2 :(得分:0)
您的期望是正确的!这是因为GCC的STL分配策略。 GCC使用启发式方法。例如,您可能需要重新插入对象。所以在整个向量消失之前,你对MyObject的析构函数的调用是内部的null语句!可在此处找到完整说明:https://gcc.gnu.org/onlinedocs/libstdc++/manual/memory.html。
根据上述链接的说明:要关闭STL优化,请设置GLIBCXX_FORCE_NEW。 我试过这样:
export GLIBCXX_FORCE_NEW=1
./a.out
现在内存立即被释放!