C++ 如果我只给std::vector一个指向我的对象的指针,它会占用什么内存?
有一些事情我不明白,我非常希望能澄清一下。我知道有很多关于std::containers和内存未释放的信息,但我仍然不理解一个特定的事实 下面是一个最小的程序,它代表了我在生产系统中遇到的一个问题。在注释中有在Ubuntu上等待std::cin时从/proc/proc_NUM/status读取的内存消耗。评论中也有问题C++ 如果我只给std::vector一个指向我的对象的指针,它会占用什么内存?,c++,linux,memory,vector,stl,C++,Linux,Memory,Vector,Stl,有一些事情我不明白,我非常希望能澄清一下。我知道有很多关于std::containers和内存未释放的信息,但我仍然不理解一个特定的事实 下面是一个最小的程序,它代表了我在生产系统中遇到的一个问题。在注释中有在Ubuntu上等待std::cin时从/proc/proc_NUM/status读取的内存消耗。评论中也有问题 #include <iostream> #include <stdlib.h> #include <fstream> #include <
#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;
}
#包括
#包括
#包括
#包括
类MyObject
{
公众:
MyObject(整数r=1000)
:数组(新浮点[r])
{
对于(inti=0;iVMSize与范围语言中范围的输入和输出几乎没有关系(是否存在没有范围的编程环境?)
VMSize反映操作系统实际必须使用哪个内存来满足程序的内存需求。例如,如果您使用malloc
、new[]
或匿名mmap
分配了一大块内存,则地址空间只会被保留,而不会被占用,因此不会显示在VMSize中
此外,大多数运行时库都以大块的形式分配内存,然后从这些大块中分割对象分配;释放对象后,只有大块中的空间被标记为空闲,并可能被回收用于下一次分配。释放如此大块内存的一个典型提示是,如果从中分配的所有对象都被释放,则因此,您的STD::vector和您手动分配的对象可能是从同一个HUK中分配的,STD::向量实例,它阻止了它返回到系统。但是这只是猜测。细节取决于所使用的C++运行库。在范围语言中输入和离开范围(是否存在没有范围的编程环境?)
VMSize反映操作系统实际必须使用哪个内存来满足程序的内存需求。例如,如果您使用malloc
、new[]
或匿名mmap
分配了一大块内存,则地址空间只会被保留,而不会被占用,因此不会显示在VMSize中
此外,大多数运行时库都以大块的形式分配内存,然后从这些大块中分割对象分配;释放对象后,只有大块中的空间被标记为空闲,并可能被回收用于下一次分配。释放如此大块内存的一个典型提示是,如果从中分配的所有对象都被释放,则因此,您的STD::vector和您手动分配的对象可能是从同一个HUK中分配的,STD::向量实例,它阻止了它返回到系统。但是这只是猜测,细节取决于所使用的C++运行库。正如你可能知道的,C++有RAIE自动资源管理,当你离开的范围内存保留向量将被释放。这就是为什么你看到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;
}
#包括
#包括
#包括
#包括
#包括“stdlib.h”
#包括“stdio.h”
#包括“string.h”
int parseLine(字符*行){
int i=strlen(直线);
而(*line<'0'|*line>'9')line++;
第[i-3]行=“\0”;
i=atoi(线);
返回i;
}
int getValue(){//注意:此值以KB为单位!
FILE*FILE=fopen(“/proc/self/status”,“r”);
int结果=-1;
字符行[128];
while(fgets(第128行,文件)!=NULL){
if(strncmp(行,“VmSize:”,7)=0){
结果=解析行(行);
打破
}
}
fclose(文件);
返回结果;
}
类MyObject
{
公众:
MyObject(整数r=1000)
:数组(新浮点[r])
{
在第一个例子中,你的In=0;iP.>你在范围内创建了堆栈上的向量。正如你所知道的,C++已经自动地进行资源管理,当你离开时,保留的内存将被释放到向量中。这就是为什么你在例子的结尾看到VMyS: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;
}
#包括
#包括
#包括
#包括
#包括“stdlib.h”
#包括“stdio.h”
#包括“string.h”
int parseLine(字符*行){
int i=strlen(直线);
而(*line<'0'|*line>'9')line++;
第[i-3]行=“\0”;
i=atoi(线);
返回i;
}
int getValue(){//注意:此值以KB为单位!
FILE*FILE=fopen(“/proc/self/status”,“r”);
int结果=-1;
字符行[128];
while(fgets(第128行,文件)!=NULL){
if(strncmp(行,“VmSize:”,7)=0){
结果=解析行(行);
打破
}
}
fclose(文件);
返回结果;
}
类MyObject
{
公众:
MyObject(整数r=1000)
:数组(新浮点[r])
{
对于(int i=0;i您的期望是正确的!发生这种情况是因为GCC的STL分配策略。GCC使用启发式。例如,您可能需要重新插入对象。因此,在整个向量消失之前,您对MyObject析构函数的调用在内部是null语句!完整解释可在此处找到:
根据上面链接的解释:要关闭STL优化,请将GLIBCXX\u FORCE\u设置为NEW。
我试着这样做:
export GLIBCXX_FORCE_NEW=1
./a.out
现在内存立即被释放了!您的期望是正确的!这是因为GCC的STL分配策略。GCC使用启发式。例如,您可能需要重新插入对象。因此,在整个向量消失之前,您对MyObject析构函数的调用在内部是null语句!完整解释如下: