【问题标题】:Strange behaviour with a vector of pointers指针向量的奇怪行为
【发布时间】:2013-03-31 17:05:12
【问题描述】:

当我运行这段简单的代码时,我很难理解我得到的输出

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

【问题讨论】:

  • 你知道自己做错了,为什么对结果感到惊讶?
  • delete 不会清除其内部数据。
  • 你专注于错误的事情。请阅读我的其他 cmets。

标签: c++ pointers memory vector


【解决方案1】:

您有未定义的行为。这是由于您访问了不存在的std::vector 元素造成的。未定义的行为意味着任何事情都可能发生。甚至看起来应该被销毁的对象仍然存在。

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

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

【讨论】:

  • 那么,为什么内存没有下降呢?
  • 但是我有一个算法需要在 for 循环的迭代中立即释放类似类型的向量。有没有办法用这种方法做到这一点?当我删除不在向量中的指针时,内存会立即释放...
  • @Gonçalo 相信你的编译器和操作系统会为你管理这个。只需编写代码,然后,如果您测量存在性能问题,您是否应该开始调查此问题。我敢打赌根本没有问题。您的迭代可能只是重用分配的内存。
  • 这正是我问这个问题的原因。我正在做一个物理模拟,需要在每个循环中存储大量数据,进行处理然后快速释放。我现在的行为是一个 for 循环,在调用删除我正在使用的所有向量之后,只是继续填充 RAM 而不是清除它。
  • @Gonçalo:您确定要删除分配的所有内容吗?免费存储应该设法重用已删除的内存而不填满 RAM。如果您有内存泄漏,那么像 Valgrind 这样的工具可能会帮助您追踪它。
【解决方案2】:

我认为问题在于您阅读矢量的方式:

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

通过这一行,您正在阅读超出矢量末尾的内容。 即使它的内容被删除,它也可能会在内存中保留一段时间。这意味着一旦它被删除,您就无法再确定这些位置中保存的内容是删除之前存储的内容,但它可以是您存储的内容。

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

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

      猜你喜欢
      • 2012-07-12
      • 1970-01-01
      • 1970-01-01
      • 2020-01-22
      • 1970-01-01
      • 2020-11-28
      • 2021-07-01
      • 2019-04-27
      • 2012-05-29
      相关资源
      最近更新 更多