用指针向量的奇怪行为

时间:2013-04-09 10:04:43

标签: c++ pointers memory vector

我在理解运行这段简单代码时得到的输出时遇到了一些麻烦

#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:我知道未定义的行为,忘记清除后的访问,我只想要一种有效的方法来立即释放内存,就像我删除常规指针一样。

3 个答案:

答案 0 :(得分:4)

您有未定义的行为。这是因为您访问了std::vector中不存在的元素。未定义的行为意味着任何事情都可能发生。甚至可能看起来应该被摧毁的物体仍在那里。

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

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

答案 1 :(得分:1)

删除从免费商店分配的内存不保证将其返回到操作系统,或使其无法访问。通常,小分配由进程内的堆管理;它从系统中分配一个大块,并分配较小的块;已删除的内存将返回到该堆。这比为每次分配进入系统要高效得多。

这意味着删除的内存可能仍然可以访问,并且在重用之前,可能仍然包含删除时的任何数据。因此访问它会产生未定义的行为,而不是任何明确定义的错误。

答案 2 :(得分:0)

我认为问题在于你正在阅读你的载体:

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

使用此行,您将在向量的末尾读取。 即使它的内容被删除,它也可能会在内存中保留一段时间。这意味着一旦删除它,您就不能再确定那些位置中的保留是否是删除前存储的内容,但它可以是您存储的内容。

就像从HD中删除文件一样。这些位实际上一直存在,直到被重写,它们被设置为未使用。