C++ 关于异常安全和内存泄漏的一些问题

C++ 关于异常安全和内存泄漏的一些问题,c++,exception,memory-leaks,valgrind,C++,Exception,Memory Leaks,Valgrind,如果我有一个类a,某个主体使用我的代码创建a的对象,然后调用DoSth(),而不调用try catch,内存会泄漏吗?valgrind报告中可能丢失且仍可访问是否表明内存泄漏?如果没有,如何避免?更重要的是,A的构造函数是不安全的,对吗?我是否必须使用智能指针来替换原始指针Animal*?还有一种叫做“复制和交换”的策略,何时使用?因为new操作符可能会抛出异常,所以当我想在堆上动态分配内存时,我不太清楚该怎么做 代码 瓦尔格林报告 Valgrind的报告显示了一个潜在的内存泄漏,因为您让异常冒

如果我有一个类
a
,某个主体使用我的代码创建
a
的对象,然后调用
DoSth()
,而不调用
try catch
,内存会泄漏吗?valgrind报告中可能丢失且仍可访问是否表明内存泄漏?如果没有,如何避免?更重要的是,
A
的构造函数是不安全的,对吗?我是否必须使用智能指针来替换原始指针
Animal*
?还有一种叫做“复制和交换”的策略,何时使用?因为new操作符可能会抛出异常,所以当我想在堆上动态分配内存时,我不太清楚该怎么做

代码 瓦尔格林报告
Valgrind的报告显示了一个潜在的内存泄漏,因为您让异常冒泡到应用程序级别,这会杀死应用程序。然后释放资源

但是,需要注意的是:

1) 如果函数可能引发异常,则应在异常到达应用程序级别之前处理该异常(在该级别,异常将终止应用程序-异常的概念是允许您优雅地处理错误)

2) 为什么要在堆上分配
动物
?在这种设置中,它可以很容易地分配到堆栈上,在这种情况下,Valgrind中也不会显示潜在的泄漏


如果您担心
new
抛出异常(实际上,这通常只在内存不足时发生……所以不太常见),则需要在单独的函数中定义初始化(即使是智能指针也无法避免该问题),或者在构造函数中有一个try-catch块,或者不要将
Animal
放在堆上。

在这种情况下:否,因为“a”是堆栈分配的,当异常导致堆栈展开时,它将被释放(调用其析构函数)。如果在堆上分配了“a”(或者在“DoSth()”中分配内存,但由于异常而没有释放内存),则可能会发生泄漏。为什么要在堆上分配
Animal
对象?@ZacHowland这只是一个模拟具有指针数据成员的类的示例。这个类可能会在运行时抛出异常。谢谢!扎克·霍兰德。在阅读了“高效C++”中关于异常安全的章节后,我开始关注我的代码。现在,我感觉好多了。。。
class A
{
public:
    A(const string& petname, int petage)
        :pet_(new Animal(petname, petage))
    {

    }

    ~A()
    {
        delete pet_;
    }

    void DoSth()
    {
        // do sth...
        throw;
    }

private:
    Animal* pet_;
};

int main(int argc, char const *argv[])
{
    A a("Kitty", 3);
    a.DoSth();
    return 0;
}
==2799== LEAK SUMMARY:
==2799==    definitely lost: 0 bytes in 0 blocks
==2799==    indirectly lost: 0 bytes in 0 blocks
==2799==      possibly lost: 30 bytes in 1 blocks
==2799==    still reachable: 16 bytes in 1 blocks
==2799==         suppressed: 0 bytes in 0 blocks