指针向量的奇怪行为

Strange behaviour with a vector of pointers

本文关键字:向量 指针      更新时间:2023-10-16

当我运行这段简单的代码

时,我在理解输出时遇到了一点麻烦
#include <vector>
#include <iostream>
#include "LxUNIXsys.h"
using namespace std;
int main(int argc, char** argv) {
  //memory management class
  LxUNIXsys mem_manager;
  vector <double*> vec;
  mem_manager.DumpMemoryInfo();getchar();
  for(int i =0; i < 3; i++) vec.push_back(new double (3));
  for(int i =0; i < vec.size(); i++) cout << *vec[i] << endl;
  mem_manager.DumpMemoryInfo();getchar();
  for(int i =0; i < vec.size(); i++) delete vec[i];
  vec.clear();
  for(int i =0; i < 3; i++) cout << *vec[i] << endl;
  cout <<"size of vec " <<vec.size() << endl;
  mem_manager.DumpMemoryInfo();
  return 0;
}

LxUNIXsys是一个类,我正在使用的内存转储和方法,我从它调用是:

void LxUNIXsys::DumpMemoryInfo() {
  pid_t id = getpid();
  //  cout << "id = " << id << endl;
  stringstream ss("");
  ss << "pmap -d " << id  << " | grep private ";
  //  cout << ss.str().c_str() << endl;
  cout << "Memory dump: [pid = " << id << " ] " << flush; system(ss.str().c_str());
}

得到的输出是:

Memory dump: [pid = 17012 ] mapped: 51476K    writeable/private: 7452K    shared: 0K
3
3
3
Memory dump: [pid = 17012 ] mapped: 51480K    writeable/private: 7456K    shared: 0K
3
3
3
size of vec 0
Memory dump: [pid = 17012 ] mapped: 51480K    writeable/private: 7456K    shared: 0K

基本上,我删除了指针,不仅信息还在那里,而且我可以在clear()之后访问它。

我也尝试使用delete[]删除vec,但结果是相同的。

PS:我知道智能指针的存在,但我想知道为什么这段代码没有达到预期的效果。

PPS:我知道未定义的行为,忘记清除后的访问,我只是想要一个有效的方式立即释放内存,就像当我删除一个常规指针

您有未定义行为。这是由于你访问了std::vector中根本不存在的元素。未定义行为意味着任何事情都可能发生。甚至可能出现应该销毁的对象仍然存在的情况。

c++标准没有说明操作系统应该如何管理内存的分配和释放。它简单地给出了程序可以依赖的规则。为这三个double分配的内存没有理由不能被操作系统回收,比您要求的时间稍晚一点。你不能再依赖它了。你唯一可以依赖的是,你不应该在std::vector的范围之外访问。

这正是标准将其指定为未定义行为的原因。它给了操作系统或环境执行内存管理的余地,但它选择,同时仍然给你的程序的规则来依赖定义良好的行为。

删除从自由存储区分配的内存并不能保证将其返回给操作系统,或者使其无法访问。通常,小的分配由进程中的堆管理;它从系统中分配了一大块,并分配了较小的部分;删除的内存返回到该堆。这比每次分配都到系统中要有效得多。

这意味着被删除的内存仍然可以访问,并且在它被重用之前,可能仍然包含删除时存在的任何数据。所以访问它会给出未定义的行为,而不是任何定义良好的错误。

我认为问题出在你读取矢量的方式上:

for(int i =0; i < 3; i++)

在这一行中,您读取的内容超出了vector的末尾。即使它的内容被删除了,它也可能会在内存中停留一段时间。这意味着一旦它被删除,你就不能再确定在这些位置上保存的是删除前存储的内容,但它可以是你存储的内容。

这就像从你的HD中删除一个文件。在重写之前,这些位实际上一直存在,它们只是被设置为未使用