Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/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++ 如果我只给std::vector一个指向我的对象的指针,它会占用什么内存?_C++_Linux_Memory_Vector_Stl - Fatal编程技术网

C++ 如果我只给std::vector一个指向我的对象的指针,它会占用什么内存?

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 <

有一些事情我不明白,我非常希望能澄清一下。我知道有很多关于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;
}
#包括
#包括
#包括
#包括
类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语句!完整解释如下: