【问题标题】:Clearing stack memory allocated in main()?清除在 main() 中分配的堆栈内存?
【发布时间】:2018-08-23 00:41:40
【问题描述】:

从我记事起,我就一直在调用堆指针,这反过来又让我在写作时思考它们的含义,而我意识到我不知道如何甚至是否有可能分配后,从内存中清除在 main() 中声明的堆栈变量。

显然,我可以只使用结构和析构函数或类似的,但可以说我想删除在 main() 中声明的堆栈上的数组是否可能?

【问题讨论】:

  • calling heap pointers 是什么意思?
  • 您为什么觉得有必要这样做?您是否担心不“删除在 main() 中声明的堆栈上的数组”会导致内存泄漏?如果是这样,你为什么这么认为?
  • 你为什么要这样做?如果你想销毁堆栈上的东西,你需要让它超出范围。
  • 如果有人为嵌入式系统编写代码,该系统将运行很长时间,并使用堆栈变量忽略析构函数,这不是一件坏事吗?
  • 可以将其包装在一个范围内 ({})。作用域结束时将被销毁。

标签: c++


【解决方案1】:

我想删除一个在 main() 中声明的堆栈上的数组 有可能吗?

是的。

在 main() 中(以及大多数使用自动变量的地方),您可以通过关闭包含范围来触发 dtor。

例子:

int main(int argc, char* argv[])
{
   int retVal = 0;
   int arr[10];
   T610_t  t610;
   retVal = t610.exec(argc, argv);
   // ...
   // ...  // t610 exists to end of main() scope.
   // ...  // arr[10] exists to end of main() scope
   return retVal;
}

实例 t610(用户定义的 T610_t 类型)持续程序的生命周期,即使在 exec() 返回 retVal 后未使用时也是如此;


相比之下:

int main(int argc, char* argv[])
{
   int retVal = 0;
   {
      int arr[10];
      T610_t  t610;
      retVal = t610.exec(argc, argv);
   }
   // ...   // no t610 instance exists, and arr[] is no longer accessible
   // ...
   // ...
   // ...
   return retVal;
}

在 exec() 返回 retVal 之后,实例 t610 的 dtor 在右大括号处被调用。 arr[10] 也不再存在。

大括号之后的所有行都不能访问 T610_t 和 arr[10],并且在“小范围”中抓取的任何自动内存都被“释放”以供重用。 (例如,另一个 T610_t 实例...)

T610_t 使用的空间的任何“清除”都取决于 dtor 的作用以及清除的含义。因此,例如,可以用 0 填充 T610_t 的数组数据属性(以“清除”它),并且 dtor 还释放内存以供重用。请记住,当您没有“新建”时不要删除。

【讨论】:

    【解决方案2】:

    不,您不能真正将变量移出当前的本地范围。

    这不是您应该关心的事情 - 编译器会处理那里的所有事情。

    如果您担心隐私,当然可以在使用后将变量置空。

    【讨论】:

    • 你为什么这么说?当然你可以清除一个局部变量。您只需要在当前范围内创建另一个本地范围,并在那里声明您的变量。事实上,许多 RAII 惯用语功能取决于作用域局部性。
    【解决方案3】:

    一个半答案来展示一个被忽略的实际答案的技巧。 (编辑:在发布时忽略已更改)

    如果您在堆栈上分配了一大块内存(自动分配)并且您需要返回该内存而不从函数返回,您可以通过调用另一个函数来引入新范围

    int get_and_compute()
    { 
        int array[1024*1024];
        read_in_a_lot_of_inputs(array);
        return compute_stuff_with__array(array);
    } 
    
    int main()
    {
        int result = get_and_compute();
        // now you have enough memory to call 
        job_that_takes_a_lot_of_RAM(result);
    }
    

    或者用一组大括号将相关代码括起来

    int main()
    {
        int result = 0;
        { //introduce a new scope
            int array[1024*1024];
            read_in_a_lot_of_inputs(array);
            result = compute_stuff_with__array(array);
        } // array goes out of scope here
        // now you have enough memory to call 
        job_that_takes_a_lot_of_RAM(result);
    }
    

    大多数时候我更喜欢选项 1,添加一个函数,但有时额外的函数没有多大意义。选择最容易阅读、编写和维护的选项。

    【讨论】:

      【解决方案4】:

      我想删除一个在 main() 中声明的堆栈上的数组,这可能吗?

      只需让执行超出声明自动变量的范围即可:

      int main() {
          {
              int arr[10];
          }
          // arr is destroyed, and further local variables can reuse its memory
      }
      

      【讨论】:

        猜你喜欢
        • 2011-08-17
        • 2017-01-20
        • 2021-04-08
        • 2018-07-24
        • 2011-10-09
        • 2021-08-30
        • 2011-05-28
        • 2012-12-05
        相关资源
        最近更新 更多