我正在使用 C++ 实现 C-API,并且在接口(interface)处我必须将类似 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->message
分配失败,它会泄漏 c
。
那么我的问题是:我应该如何理想地处理这种情况?
到目前为止我想出了什么:
/* ... */
} catch (std::bad_alloc exception) {
if (c != nullptr) {
delete c;
}
return nullptr;
}
/* ... */
在 C++ 中有更好的方法吗?
如果使用 new
和 delete
管理内存并且您碰巧在捕获 std::bad_alloc
的相同 try
block 。
这是否可以使用智能指针或其他方式解决?
最佳答案
I am responsible for the memory of the data structure
How to prevent memory leak
解决方案是让其他人负责 :) 这可能听起来很讽刺,但我发现它很有见地。
将内存管理代码放入 RAII 容器中,其唯一职责是在超出范围时释放内存。从 C++11 开始,RAII 容器可以在没有开销的情况下实现,并且已经在标准库中为您实现:std::unique_ptr
。
只要内存由唯一指针持有,如果唯一指针由于异常或其他原因超出范围,内存将被释放。底层裸指针可以从唯一指针释放,并在所有可能抛出的代码成功执行后返回。
This problem can also happen in C++ only applications
RAII 容器在 C++ 中甚至更好,您可以在对象的整个生命周期内保留容器,而不是将内存释放到野外。
附言。
if (c->message != nullptr) {
delete[] c->message;
}
这个测试完全是多余的,这可以简化为
delete[] c->message;
关于c++ - 如何防止连续使用 'new' 分配失败时发生内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45202932/