c++ - 如何防止连续使用 'new' 分配失败时发生内存泄漏

标签 c++ c++11 memory-management memory-leaks

我正在使用 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++ 中有更好的方法吗?

如果使用 newdelete 管理内存并且您碰巧在捕获 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/

相关文章:

带删除的 C++ 映射迭代

macos - Java 问题 : Memory and CPU usage in MAC OS

c++ - 在 C++ 中就地 bool AND 和 OR?

java - 将 .const 文件 (c++) 转换为 .java 类时出现问题

c++ - 消除多重继承中的类成员歧义

java - 测量和监控大型 HashMap 的大小

IOS @property, @synthesize 内存泄漏

c++ - 从 TArray<uint8> 中提取 float32

c++ - 为什么 std::reference_wrapper 显式定义了复制赋值运算符?

c++ - 检查 C++ 类是否公开继承自带有匿名参数的模板类