在 class 函数中使用 "new" 和 "delete"
using "new" and "delete" inside class function
我想确保根据需要使用 new
和 delete
释放堆内存。
以下函数 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++ 的文章,并听说很多内存泄漏问题时...这正是导致它们的原因。
我想确保根据需要使用 new
和 delete
释放堆内存。
以下函数 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++ 的文章,并听说很多内存泄漏问题时...这正是导致它们的原因。