【问题标题】:C++ macros to ensure used memory is freed?确保释放已用内存的 C++ 宏?
【发布时间】:2011-05-06 19:19:30
【问题描述】:

所以我有点不习惯,正在阅读有关newdelete 和指针的信息,我确信在我的一生中我会忘记太多的删除。所以我想知道像下面这样的宏是否会比它的价值更麻烦。

#define withObject(ptr, value, BODY)                       \
{                                                           \
     ptr = value;                                           \
     BODY                                                   \
     delete ptr;                                            \ 
     ptr=NULL                                               \
}

这个宏会导致一些问题或以意想不到的方式运行吗?

编辑:哎呀,我在释放时离开了 d。好的,谢谢大家的回答。

【问题讨论】:

    标签: c++ memory-management memory-leaks macros


    【解决方案1】:

    不,不要这样做。它不会防止内存泄漏或杂散指针。相反,请阅读智能指针。当前的标准提供了auto_ptr 的形式,但还有更多(和更好的)可用,具体取决于您的 C++ 平台。

    另外,我怀疑您可能过度使用 new 和 delete - 在您的代码中应该很少使用它们。您应该更喜欢使用值。所以不要像这样:

    string * s = new string ( "foobar" );
    ....
    delete s;
    

    你应该简单地写:

    string s( "foobar" );
    

    并让编译器为您管理字符串的生命周期。

    【讨论】:

    • @Martin 对不起,我不相信允许编辑答案,除了删除危险的错误、拼写错误,当然还有 CW 的情况。
    • @unapersson:来自the FAQ:“如果您对您的问题和答案被其他受信任的用户编辑的想法感到不满意,那么这可能不适合您。”
    • @Brian 正如我的评论所建议的那样,我对此感到满意,但如果它改变了我回答的意义或主旨,则不会。
    • @unapersson:恕我直言,暗示 auto_ptr 是完全错误的。我希望你知道为什么。
    • @rubenvb 如果您的意思是因为它将在下一个标准中被弃用,那么下一个标准还没有出现在我们身边,我们必须使用我们目前拥有的 C++ 平台。你认为我所说的“更多(和更好的)”是什么意思?此外,尽管已弃用,但 auto_ptr 将加入一长串已弃用的东西,这些东西实际上从未从标准中删除。
    【解决方案2】:

    这里无需重新发明轮子,你正在寻找smart pointers

    非常有用的Boost 库具有smart pointer 功能。

    【讨论】:

      【解决方案3】:

      谷歌RAII idiom;它是一样的,但不是那么老套;然后,您可以使用无处不在的智能指针(当它们超出使用/范围时自动释放内存)将其应用于您的动态分配。

      Boost 包含最著名/广泛使用的智能指针版本(几种风格)。

      C++ 标准一直有一种残缺的智能指针,名为auto_ptr。这是一个有警告但本身有用的(RTFM!)。

      C++0x 采用了一些 Boost TR1 类,包括最流行的智能指针(我希望我的措辞是正确的,因为标准语言通常非常注重细节)

      HTH

      【讨论】:

        【解决方案4】:

        您正在寻找 智能指针 模式。它是标准 C++,在 this site 有详细说明。

        【讨论】:

          【解决方案5】:

          除了您确实应该使用智能指针这一事实(即使是低级的auto_ptr 也会为您服务),BODY 可能存在问题。使用可能较大的代码段作为类函数宏的参数有其自身的陷阱。例如,如果 BODY 中有一个不带括号的逗号,那么 BODY 会变成两个参数。我不确定是否还有其他问题,因为我从未见过有人尝试过。

          不要在 C++ 中使用类似函数的宏。这很少值得。

          【讨论】:

            【解决方案6】:

            看起来您希望分配一个对象,对其进行一小段工作,然后将其删除。为此,我建议使用 std::auto_ptr。

            【讨论】:

              【解决方案7】:

              执行此类操作的惯用 C++ 方法不是使用宏,而是使用使用 Resource Acquisition is Initialization 的“智能指针”类。例如,Boost 的 scoped_ptr 在您的宏有意义的上下文中会很好地工作。

              我将在这里绘制一个智能指针类的草图 - 但我会遗漏很多细节。这只是为了让您了解它们的工作原理。改用 scoped_ptr,他们没有遗漏任何内容。

              template <typename T>
              class smartptr<T> {
              public:
                  smartptr() : ptr(new T) {}
                  smartptr(T* p) : ptr(p) {}
                  ~smartptr() { delete ptr }
                  T& operator*() { return *ptr; }
                  T* operator->() { return ptr; }
              private:
                  T* ptr;
              }
              

              【讨论】:

              • 对于初学者来说,留下这样的损坏的代码是非常危险的。他们不会意识到这是多么危险。如果您不能提供完整的实现,请不要显示代码。
              • 实现自己的智能指针就像实现自己的 PRNG 或加密——几乎总是一个坏主意。他们真的很难做对。
              • 我认为演示引擎盖下发生的事情的代码很有价值,而且我认为我的代码遗漏了很多,以至于它不会绊倒任何人,因为除了玩具场景之外它实际上无法使用.
              【解决方案8】:

              这个宏会导致一些问题或以意想不到的方式运行吗?

              如果 BODY 抛出异常,那么 delete 将被跳过。

              解决方案是使用“RAII”成语。它是现代 C++ 编程中最重要的概念之一。

              【讨论】:

                【解决方案9】:

                我认为更好的解决方案是创建一个分配和删除宏,而不是一个包罗万象的宏。那是一件非常混乱的事情,不是很有帮助

                当我用 C 编程时,我通常会做以下事情:

                #define ALLOC_ARY(type, sz) (type*)calloc(sz, sizeof(type))
                #define ALLOC_STR(sz) ALLOC_ARY(char, sz)
                
                char *string = ALLOC_STR(128);
                int *array = ALLOC_ARY(int, 20);
                

                但记住在原版 C 中释放只是其中的一部分:

                free(string); string = NULL;
                free(array); array = NULL;
                

                编辑:对于 C++,其他人建议的智能指针是一个不错的方法。

                【讨论】:

                  猜你喜欢
                  • 2020-11-18
                  • 2021-03-09
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2023-03-10
                  • 2020-11-13
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多