在 class 函数中使用 "new" 和 "delete"

using "new" and "delete" inside class function

我想确保根据需要使用 newdelete 释放堆内存。

以下函数 return 是 char *。在每个函数中,我使用 new 作为 returned 值,然后我使用 delete

为函数 return 释放堆内存的正确方法吗?

const char *myIOT2::_devName()
{
    char *ret = new char[MaxTopicLength2];
    if (strcmp(addGroupTopic, "") != 0)
    {
        snprintf(ret, MaxTopicLength2, "%s/%s/%s", prefixTopic, addGroupTopic, deviceTopic);
    }
    else
    {
        snprintf(ret, MaxTopicLength2, "%s/%s", prefixTopic, deviceTopic);
    }
    return ret;
}
const char *myIOT2::_availName()
{
    char *ret = new char[MaxTopicLength2];
    const char *DEV = _devName();
    snprintf(ret, MaxTopicLength2, "%s/Avail", DEV);
    delete DEV;
    return ret;
}

要指出的是:我 DEV: const char *DEV = _devName(); 是为了在 snprintf(ret, MaxTopicLength2, "%s/Avail", DEV); 中将其用作参数只是为了能够 delete 之后作为 delete DEV; - 这是正确的吗?

ret 分配的内存:

const char *myIOT2::_devName()
{
    char *ret = new char[MaxTopicLength2];
    return ret;
}

在下面,您会看到通过删除 DEV,您将释放内存,因为它实际上是 ret。但是这一次,您应该在其他地方删除 ret2,因为它是 return 值,并且无法在该范围内删除它:

const char *myIOT2::_availName()
{
    char *ret2 = new char[MaxTopicLength2];
    const char *DEV = _devName();
    delete[] DEV;
    return ret2;
}

另外,请注意以下几点:

char* str = new char [30]; // Give str a memory address.

// delete [] str; // Remove the first comment marking in this line to correct.

str = new char [60]; /* Give str another memory address with
                                                    the first one gone forever.*/

delete [] str; // This deletes the 60 bytes, not just the first 30.

至少在我看来,你真的只有两个理智的选择。一种是让调用者处理所有的内存管理。另一个是被调用者处理所有的内存管理。

但是您现在正在做的事情(被调用方处理分配,调用方处理 de-allocation)是导致疯狂和内存泄漏的途径。

如果调用者要管理内存,这一切都变得相当简单:

const char *myIOT2::_devName(char *ret, size_t maxlen)
{
    if (strcmp(addGroupTopic, "") != 0)
    {
        snprintf(ret, maxlen, "%s/%s/%s", prefixTopic, addGroupTopic, deviceTopic);
    }
    else
    {
        snprintf(ret, maxlen, "%s/%s", prefixTopic, deviceTopic);
    }
    return ret;
}

如果被调用者要处理所有的内存管理,你通常会使用std::string。但是,由于您使用的是 Arduino,std::string 不可用,您需要改用他们自己的 String class。无论哪种方式,您只需分配一个 String 对象并将您的内容放入其中。它负责保存内容的实际内存分配,并在 String 对象被销毁时释放其内容。

鉴于 Arduino 上通常可用的内存很少,让调用者分配内存 通常 会更好。但是(特别是如果这种情况不经常发生,那么你就不会 运行 进入堆碎片问题)在堆上分配 space 也可以很好地工作。

但我要重复一遍:试图混合内存管理以便被调用者分配和调用者删除……是噩梦。当您大约在 1993 年阅读有关 C++ 的文章,并听说很多内存泄漏问题时...这正是导致它们的原因。