2

我想要一个指向静态数据的指针数组。例如

  void func(...) {
     ...
     static int mysize = initial_size;
     static double* d[3] = {new double[mysize], new double[mysize], new double[mysize]};
     for(int i=0; i < 3; ++i) {
        if(cond) {
           //-re-allocate d if necessary.
           use d here;
        }
        else {
           use d here;  //-since d is static; it persists and so this is justified?
        }
     }
     //-Can I get away with not deleting d here??
  }

我的理由是,因为 d 是一个指向静态双精度的指针数组;它在函数内部分配一次,所以当一切超出范围时,它会被删除吗?我不知何故认为没有。这可能是一厢情愿并导致内存泄漏?

也许我最好在这里使用静态 C++ 向量?我想在这里使用静态,以便在满足某些条件时(例如,如果满足某些条件,例如 cond 或其否定)重新使用 d 中先前计算和存储的数据。希望这是有道理的,并提前感谢任何想法。

4

3 回答 3

3

删除将是一个错误d,因为它没有分配给new。但是,由于单个元素用 分配的new,因此您需要小心避免孤立它们的内存。

于 2012-05-24T22:32:46.853 回答
1

正如@AdamLiss 上面所说,如果您在重新分配之前不小心删除现有数组,则可能会在必要时在重新分配 d步骤中泄漏内存:

void func(...) {
  static int mysize = initial_size;
  static double* d[3] = {new double[mysize], new double[mysize], new double[mysize]};
  for(int i=0; i < 3; ++i) {
    if(cond) {
      d[i] = new double[2*mysize];  // LEAK!
      use d here;

即使您记得像这样删除它:

void func(...) {
  static int mysize = initial_size;
  static double* d[3] = {new double[mysize], new double[mysize], new double[mysize]};
  for(int i=0; i < 3; ++i) {
    if(cond) {
      delete[] d[i];
      d[i] = new double[2*mysize];

有一个错误,因为新分配可能会引发异常,d[0]指向已删除的内存,但没有办法告诉这一点,所以当函数 next 被调用时,如果d[0]被取消引用,它将是未定义的行为。

这没关系:

void func(...) {
  static int mysize = initial_size;
  static double* d[3] = {new double[mysize], new double[mysize], new double[mysize]};
  for(int i=0; i < 3; ++i) {
    if(cond) {
      double* tmp = new double[2*mysize];
      std::swap(tmp, d[i]);
      delete[] tmp;

但是,如果您使用向量来管理动态内存,则可以避免此类问题:

void func(...) {
  int mysize = initial_size;
  typedef std::vector<double> dvec;
  static dvec d[3] = {dvec(mysize), dvec(mysize), dvec(mysize)};
  for(int i=0; i < 3; ++i) {
    if(cond) {
      //-re-allocate d if necessary.
      d[i].resize(2*mysize);
      use d here;
    }
    else {
      use d here;
    }
  }
}

这还具有能够查询现有大小的优点,通过d[i].size()在重新分配时不必手动将元素从旧数组复制到新数组

于 2012-05-24T23:09:23.083 回答
1

您的代码基本上没问题,尽管有一些影响:

  • purify、insure 和 valgrind 等内存使用检查工具可能会报告更多关于潜在内存泄漏的噪音,但这本身只是噪音。

  • static使创建线程安全代码变得更加困难——让调用者d作为函数参数向下传递,以func允许特定于线程的副本、特定于应用程序区域的副本、更容易的单元测试而无需重新启动进程,以及对生命周期的完全客户端控制。

  • 假设您的应用程序引入了一个额外的阶段/阶段,在完成对它的调用后, func()它开始在关闭之前进行一些其他内存密集型计算 - 内存仍将被分配。这对您来说可能无关紧要,特别是如果您有足够的虚拟地址空间并且可以将其换出到磁盘,但随着代码的发展,这是一个额外的潜在维护问题。

于 2012-05-25T00:03:58.510 回答