我正在使用C ++实现一个C-API,在接口处我必须将类似C ++的数据结构转换为C-API的现有数据结构。
我负责数据结构的内存,所以我可以使用new和delete,但是根据我的理解,下面的C ++ 11代码可能会有内存泄漏(这只是一个愚蠢的例子):
#include <string>
#include <new>
struct container {
char *message;
};
/* converts an std::string to a C data structure */
container *create_container(const std::string& message) {
container *c = nullptr;
try {
container *c = new container;
c->message = new char[message.length() + 1];
message.copy(c->message, message.length());
c->message[message.length()] = '\0';
} catch (std::bad_alloc exception) {
return nullptr;
}
return c;
}
void destroy_container(container *c) {
if (c != nullptr) {
if (c->message != nullptr) {
delete[] c->message;
}
delete c;
}
}
int main(void) {
container *c = create_container("message");
destroy_container(c);
return 0;
}
如果c
的分配失败,它将泄漏c->message
。
所以我的问题是:我应该如何理想地处理这种情况?
到目前为止我想出了什么:
/* ... */
} catch (std::bad_alloc exception) {
if (c != nullptr) {
delete c;
}
return nullptr;
}
/* ... */
在C ++中有更好的方法吗?
如果内存是使用new
和delete
管理的,并且您恰好在同一new
块中使用try
两次,则此问题也可能发生在仅限C ++的应用程序中std::bad_alloc
。
这可能是使用智能指针或其他方式解决的吗?
答案 0 :(得分:2)
我负责数据结构的记忆
如何防止内存泄漏
解决方案是让其他人负责:)这可能听起来很讽刺,但我发现它很有见地。
将内存管理代码放在RAII容器中,其唯一的职责是在超出范围时释放内存。从C ++ 11开始,即RAII容器可以在没有开销的情况下实现,并且已经在标准库中实现:std::unique_ptr
。
只要内存由该唯一指针保持,如果唯一指针由于异常或其他原因而超出范围,则将释放内存。可以从唯一指针释放基础裸指针,并在所有可能抛出的代码成功执行后返回。
仅在C ++应用程序中也会发生此问题
RAII容器在C ++中更好,你可以在容器的整个生命周期内保留容器,而不是将内存释放到野外。
PS。
if (c->message != nullptr) {
delete[] c->message;
}
测试完全是多余的,可以简化为
delete[] c->message;
答案 1 :(得分:0)
将所有指针存储在unique_ptr
中。如果C ++ 14或更好的理想情况下创建make_unique
(对于具有make唯一的数组可能需要17)。
分配完所有内容并检查.release
唯一指针后。