如何通过连续使用'new'来防止分配失败时的内存泄漏

时间:2017-07-19 23:57:07

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

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

如果内存是使用newdelete管理的,并且您恰好在同一new块中使用try两次,则此问题也可能发生在仅限C ++的应用程序中std::bad_alloc

这可能是使用智能指针或其他方式解决的吗?

2 个答案:

答案 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唯一指针后。