在C+中,正确的错误处理方法是什么+; 一个是使用C++异常:尝试catch块。但当出现异常时,释放动态内存将是一个问题

在C+中,正确的错误处理方法是什么+; 一个是使用C++异常:尝试catch块。但当出现异常时,释放动态内存将是一个问题,c++,error-handling,C++,Error Handling,第二种是使用C样式:errno变量 第三种方法是错误时返回-1,成功时返回0:) 中型项目应选择哪种方式?为什么?还有其他更好的方法吗 但当出现异常时,释放动态内存将是一个问题 不,不是标准::向量v(100)完成 这里的概念被称为范围限制资源管理(SBRM),也被更常见(也更尴尬)的名称资源获取是初始化(RAII)所知。基本上,所有资源都包含在某个对象中,该对象将清理析构函数中的资源(该析构函数始终保证为自动分配的对象运行)。因此,无论函数是否正常存在或通过异常存在,析构函数都将运行,并且资源

第二种是使用C样式:errno变量

第三种方法是错误时返回-1,成功时返回0:)

中型项目应选择哪种方式?为什么?还有其他更好的方法吗

但当出现异常时,释放动态内存将是一个问题

不,不是<代码>标准::向量v(100)完成

这里的概念被称为范围限制资源管理(SBRM),也被更常见(也更尴尬)的名称资源获取是初始化(RAII)所知。基本上,所有资源都包含在某个对象中,该对象将清理析构函数中的资源(该析构函数始终保证为自动分配的对象运行)。因此,无论函数是否正常存在或通过异常存在,析构函数都将运行,并且资源将被清理

永远不要在需要显式释放的地方进行分配,使用容器和智能指针

第二种是使用C样式:errno变量

第三种方法是错误时返回-1,成功时返回0:)

它们如何帮助您解决释放动态内存的问题?他们还使用提前退出策略,与抛出相同


所以,总之,它们没有C++异常的优势(根据你的)。

抛出异常。当抛出异常时,总是调用变量的析构函数,如果基于堆栈的变量在发生异常后没有进行清理(例如,如果您在需要删除结果时使用了原始指针),那么您将得到应得的结果。使用智能指针,没有内存泄漏。

< P>查看萨特的这个关于C++的尝试捕获的注释。并仔细阅读他的整套文章。他确实有很多话要说,什么时候以及如何检查并避免出现错误,以及如何以最好的方式处理错误。

首先,你应该争取一个错误案例最少的程序。(因为错误并不酷。)

异常是一个很好的工具,但是:为“异常情况”保留它们,不要使用它们来控制程序的流程

例如,不要使用异常来测试用户输入是否正确。(对于这种情况,请返回错误代码。)

但当引发异常时,释放动态内存将是一个问题


释放内存(或任何其他资源)不会突然成为一个问题,因为您不使用异常。在抛出异常时处理这些问题的技术可以很容易,在出现“错误条件”时也可以很容易。异常有利于将控制从一个上下文传递到另一个上下文。
您可以让编译器在上下文之间展开堆栈,然后在新上下文中补偿异常(然后希望继续)

如果您的错误发生并且可以在相同的上下文中更正,那么错误代码是处理和清理错误的好方法(不要认为这意味着您不应该使用RAII,您仍然需要它)。但是,例如,在一个类中,函数中发生错误,调用函数可以纠正该类型的错误(那么这可能不是异常情况,所以没有异常),那么错误代码是有用的

当您必须从库或子系统中传递信息时,不应使用错误代码,因为您需要依赖使用代码的开发人员来实际检查和处理代码,以确保其正确工作,并且他们通常会忽略错误代码

一个是使用C++异常: 挡块。但释放动态 当出现错误时,内存将成为一个问题 提出了例外情况

@见雷伊

异常应该是处理异常运行时情况(如内存不足)的首选方法。请注意,像std::map::find这样的东西不会抛出(也不应该抛出),因为搜索不存在的密钥不一定是错误或特殊情况:函数可以通知客户端该密钥是否存在。这不像违反前置条件或后置条件,比如要求文件存在,程序才能正确运行,却发现文件不存在

如果您正确地执行异常处理(再次@see RAII),那么异常处理的美妙之处在于它避免了在整个系统中乱扔错误处理代码的需要

让我们考虑一个函数A调用函数B的情况,调用C,然后D,一直到Z。Z是唯一可以抛出的函数,A是唯一有兴趣从错误中恢复的函数(A是高级操作的入口点,例如,加载图像)。如果您坚持使用RAII,它不仅有助于异常处理,而且只需在Z中放置一行代码即可抛出异常,在a中放置一个小try/catch块即可捕获异常,并向用户显示错误消息

不幸的是,许多人并没有像在实践中那样严格遵守RAII,因此许多实际代码中的try/catch块比处理手动资源清理(不必手动)所需的要多。然而,这是您应该在代码中努力实现的理想,如果是中等规模的项目,则更为实用。同样,在现实世界中,人们常常忽略函数返回的错误代码。如果您想为健壮性付出额外的努力,那么最好从RAII开始,因为无论您使用的是异常处理还是错误代码处理,RAII都将帮助您的应用程序

有一个警告:您不应该跨越模块边界抛出异常。如果你这样做,你应该考虑错误代码之间的混合(如返回错误代码,而不是使用GLUB)。
int* p = new int(123); // can throw std::bad_alloc
int* p = new(std::nothrow) int(123); // returns a null pointer on failure