当OS无法分配内存时,使用STL的应用程序是否应该易于发生内存泄漏? [英] Are applications using STL ought to be memory-leak prone when OS cannot allocate memory?

查看:84
本文介绍了当OS无法分配内存时,使用STL的应用程序是否应该易于发生内存泄漏?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我个人不喜欢异常处理.在许多地方,建议不要将捕获异常并仍继续执行程序作为良好的编程习惯.

I personally am not fan of exception handling. As in many places it's suggested that catching exceptions and still continuing with program execution is not recommended as good programming practice.

但是,由于 STL容器会引发异常(即bad_alloc),所以除了在我们的代码中具有异常处理块外,别无选择.但是在处理我的应用程序中的STL调用时,我发现很难使应用程序具有防泄漏性和健壮性.

However, since STL containers throw exceptions (viz. bad_alloc), there is no choice than having exception handling blocks in our code. But while dealing with STL calls in my application, I am finding its very tough to make application leak-proof and robust.

下面的示例代码演示了STL(带有异常处理)如何导致内存泄漏:

A sample code below demonstrate how STL (with exception handling) might cause memory leaks:

void my_function()
{
    try
    {
        std::vector<int> integers; // It can throw bad_alloc here (1)

        for (int i=0; i<10240; i++)
        {
            int* myintptr = new (std::nothrow) int;
            if (myintptr == NULL) // Memory not allocated. But no exception thrown so I am safe to continue.
                continue;
            *myintptr = i;
            integers.push_back (*myintptr ); // It can throw bad_alloc here (2)
            delete myintptr;
        }
    }
    catch(std::bad_alloc& ba)
    {
        // If it come here after throwing exception at (1) its fine. But if it has thrown exception at (2) then it just leaked memory allocated by new int
    }
}

(当然,这只是简化版本,以演示大而复杂的代码中的类似情况.)

现在,这里可能有一些建议:

Now, there could be couple of suggestions here:

1.在最狭窄的块上使用异常处理:因此,这意味着我必须在调用push_back周围放置另一个try..catch.但是然后,如果我想在每个STL调用周围放置try ... catch块,我的代码将是什么样子?

1. Use exception handling on most narrowed block: So it means I've to place another try..catch around call push_back. But then, if I want to place try...catch block around each STL calls, how my code would look like?

2.确保您有足够的内存:也可能建议我们不要陷入OS无法分配内存的情况.因此,我们可以在继续进行STL调用之前主动检查是否有足够的内存. 但是这种策略并不总是可行的.拥有足够的可用内存并不能保证我们进一步分配内存的请求会成功(例如,假设内存是零散的. 此外,如果系统上正在运行其他消耗大量内存的应用程序,则OS可能很难在物理内存中找到要分配的空间,因此它可以拒绝该请求.)

2. Make sure you have enough memory: It might also be suggested that we shouldn't land into situation where OS cannot allocate memory. So, we can proactively check if adequate memory is available before we proceed with STL calls. But this strategy will not work always. Having enough free memory doesn't guarantee us that further requests to allocate memory would be succeeded (e.g. Say if memory is fragmented. Additionally, if there are other heavy memory consuming applications running on the system, then OS might find its very hard to find space in physical memory for allocation, so it simply could deny the request.)

所以最后一个大问题是:

So at the end the big question is:

我们如何使我们的应用程序使用STL健壮(不会崩溃,即使OS拒绝内存分配请求也能继续运行)和充分证明(即使有异常也不会泄漏)?

推荐答案

我在先前的答案中发现了一个分散的答案.我只是将其合并发布.但所有功劳归功于这些专家:

I found an answer scattered allover in previous answers. I am just posting it herewith consolidated. But all credit goes to those individual experts:

通过 DietmarKühl:

您应该了解 RAII!基本思想是,您永远不会拥有任何资源不受对象破坏后清理资源的保护. (try/catch块对于处理资源清理肯定没有用,并且通常用于处理实际问题.)

You should learn about RAII! The basic idea is that you never have any resource which isn't guarded by an object cleaning up the resource upon destruction. (try/catch blocks are certainly not useful to deal with resource clean-up and are mostly used to deal with the actual problem.)

通过 bobah :

专门用于STL内存分配-所有容器(除非存在实现错误)都是RAII,因此即使分配器抛出异常也不会导致内存泄漏.

To STL memory allocation specifically - all containers (unless have implementation bugs) are RAII so won't cause memory leaks even when allocator thrown an exception.

通过人头马(Remy Lebeau):

在您的示例中,您可以使用std :: auto_ptr(或C ++ 11中的std :: unique_ptr)来保护新产品.无需删除auto_ptr,因为它会在超出范围时自动破坏. 但是,无论何时有意删除它,都可以调用reset.

In your example, you can protect the new by using a std::auto_ptr (or std::unique_ptr in C++11). No need to delete the auto_ptr as it automatically destructs when goes out of scope. But you can call reset whenever you deliberately want to delete it.

void my_function()
{
    try
    {
        std::vector<int> integers; // It can throw bad_alloc here (1)

        for (int i=0; i<10240; i++)
        {
            std::auto_ptr<int> myintptr(new (std::nothrow) int(i));
            if (myintptr.get() == NULL) // Memory not allocated. But no exception thrown so I am safe to continue.
                continue;
            integers.push_back (*(myintptr.get()) ); // It can throw bad_alloc here (2)

            myintptr.reset(); // You can call reset to delete smart pointer (Although no need to delete in this example)
        }
    }
    catch(std::bad_alloc& ba)
    {
        // If it come here after throwing exception at (1) or (2) its fine. No leaks
    }
}


通过 user2079303 :


By user2079303:
It's also worth to note,

您可以使用保留(如果是矢量) 因为reserve可以事先保证所需的空间,所以当您推送新元素时将不会进行任何重新分配,因此也不会进行bad_alloc.

you can use reserve (in case of vector) Because reserve guarantees the required space beforehand, there will be no reallocations when you push new elements and therefore no bad_alloc.

这篇关于当OS无法分配内存时,使用STL的应用程序是否应该易于发生内存泄漏?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆