简体   繁体   English

C ++异常处理

[英]C++ Exception Handling

So I was writing some code and I noticed that apart from syntactical, type, and other compile-time errors, C++ does not throw any other exceptions. 所以我正在编写一些代码,我注意到除了语法,类型和其他编译时错误之外,C ++不会抛出任何其他异常。 So I decided to test this out with a very trivial program: 所以我决定用一个非常简单的程序来测试它:

#include<iostream>

int main() {
    std::count<<5/0<<std::endl;
return 1
}

When I compiled it using g++, g++ gave me a warning saying I was dividing by 0. But it still compiled the code. 当我用g ++编译它时,g ++给了我一个警告,说我除了0但是它仍然编译了代码。 Then when I ran it, it printed some really large arbitrary number. 然后,当我运行它时,它打印了一些非常大的任意数字。 When I want to know is, how does C++ deal with exceptions? 当我想知道的是,C ++如何处理异常? Integer division by 0 should be a very trivial example of when an exception should be thrown and the program should terminate. 整数除以0应该是一个非常简单的例子,它应该抛出异常并且程序应该终止。

Do I have to essentially enclose my entire program in a huge try block and then catch certain exceptions? 我是否必须将我的整个程序封装在一个巨大的try块中然后捕获某些异常? I know in Python when an exception is thrown, the program will immediately terminate and print out the error. 我在Python中知道抛出异常时,程序将立即终止并打印出错误。 What does C++ do? C ++做什么? Are there even runtime exceptions which stop execution and kill the program? 是否有运行时异常停止执行并终止程序?

There are runtime exceptions, but not everything that's "wrong" results in a runtime exception being thrown. 存在运行时异常,但并非所有“错误”导致抛出运行时异常。 For example, acccessing an array out of bounds or dereferencing a null pointer is simply "undefined behaviour" - meaning anything at all can happen. 例如,访问一个数组越界或解除引用空指针只是“未定义的行为” - 意味着任何事情都可能发生。 Division by zero also falls into the "undefined" category. 除零也属于“未定义”类别。

The rationale for some operations resulting in "undefined behaviour" rather than an exception is efficiency. 导致“未定义行为”而非例外的某些操作的基本原理是效率。 Suppose an out-of-bounds array access required an exception to be thrown. 假设一个越界数组访问需要抛出异常。 Then the compiler would have to generate code for each array access to checks whether it's out of bounds, and if so, throw an exception. 然后编译器必须为每个数组访问生成代码以检查它是否超出范围,如果是,则抛出异常。 That's a lot of checking, most of which is unnecessary. 这是很多检查,其中大部分是不必要的。 Instead, what compilers do is just generate the instruction for the element access assuming it is within bounds. 相反,编译器所做的只是生成元素访问的指令,假设它在边界内。 If it happens to be out of bounds, then whatever happens (eg segmentation fault) happens. 如果它碰巧超出范围,则发生任何事情(例如分段错误)。 If you want a check to be performed, you can always code it explicitly. 如果执行检查,可以始终显式编码。

This makes C++ more powerful than languages that always do checks (eg Java or python) because you can choose when you want a check done, and when you don't. 这使得C ++比总是进行检查的语言(例如Java或python)更强大,因为您可以选择何时进行检查,何时不进行检查。 (On the other hand, it makes C++ less safe than Java or python. It's a trade-off). (另一方面,它使C ++不如Java或python安全。这是一种权衡)。


As for what happens when an exception is thrown but not caught anywhere, typically compiler implementations will print an error message containing the exception's what() . 至于抛出异常但未在任何地方捕获时会发生什么,通常编译器实现将打印包含异常的what()的错误消息。 In your example that's not applicable because no runtime exception is being thrown. 在您的示例中不适用,因为没有抛出运行时异常。

Yes, there are runtime exceptions. 是的,有运行时异常。 An example is out_of_range , which is thrown by vector::at . 一个例子是out_of_range ,它由vector::at抛出。

However, division by zero is undefined (C++0x §5.6/4): 但是,除以零是未定义的(C ++0x§5.6/ 4):

If the second operand of / or % is zero the behavior is undefined. 如果/或%的第二个操作数为零,则行为未定义。

So it can fail to compile, throw a made-up exception, print "some really large arbitrary number", or segfault. 所以它可能无法编译,抛出一个组成的异常,打印“一些非常大的任意数字”或段错误。

C++ only throws standard exceptions that are well defined in the C++ standard.( Yes it includes some run-time exceptions ) C ++只抛出在C ++标准中定义良好的标准异常。( 是的,它包含一些运行时异常

An Integer divided by zero is not an standard C++ exception( Technically it is Undefined Behavior ). 除以零的整数不是标准C ++异常( 从技术上讲,它是未定义的行为 )。 So no implicit exception will be thrown. 因此不会抛出任何隐式异常。 An particular compiler might map the run-time error to some kind of an exception(You will need to check the compiler documentation for this, some compilers map divide by zero to some exception), if so you can catch that particular exception. 特定的编译器可能会将运行时错误映射到某种异常(您需要检查编译器文档,一些编译器映射除以零到某些异常),如果是这样,您可以捕获该特定异常。 However, note that this is not portable behavior and will not work for all compilers. 但请注意,这不是可移植行为,并不适用于所有编译器。

Best you can do is to check the error condition(divisor equals zero) yourself and throw an exception explicitly in such cases. 你可以做的最好是自己检查错误条件(除数等于零)并在这种情况下明确地抛出异常。

EDIT: To answer the comment 编辑:回答评论

class A
{
    public:
         void f()
         {
             int x;
             //For illustration only
             int a = 0;
             if(a == 0)
                  throw std::runtime_error( "Divide by zero Exception"); 
             x=1/a;
         }

         A()
         {
              try
              {
                   f();
              }
              catch(const std::runtime_error& e)
              {
                   cout << "Exception caught\n";
                   cout << e.what(); 
              }
         }
 };     

Visual C++ correctly flags this as a divide by zero error. Visual C ++正确地将此标记为除零错误。 So if it doesn't compile, then there is no question of running it. 因此,如果它不编译,那么就没有运行它的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM