How to register exceptions in C ++?

When writing a function, my implementation very often looks like this:

  • Subfunction call
  • If this sub-function fails (due to an exception): register this failure and interrupt the current function
  • Otherwise, continue to call other subfunctions, which, in turn, may fail

The most important part is registration. Each failed function should add a short description to the log. Thus, at the level where the exception is handled, a detailed error message may be displayed to the user.

For example, consider an application in which a new user account can be created and there is a problem connecting to the database. The following reverse stack trace:

  • SQLDriverConnect () → "SQLDriverConnect Error: Data Source Not Found and Default Driver Not Specified"
  • OpenDatabaseConnection () → "Failed to open database connection"
  • CreateUser () → "Failed to create a new user"
  • ValidateAndSaveNewUserAccount () → "Failed to save user profile"
  • Catch exception and show logged messages to user

Using the exception function, I would do it as follows:

void CreateUser()
{
    try {
        OpenDatabaseConnection();
    }
    catch(std::exception& e) {
        e.AddLog("Failed to create the new user");
        throw;
    }
    //...
}

Using a simple return value, I would write the following:

bool CreateUser(Log& log)
{
    if (!OpenDatabaseConnection(log))
    {
        log.Add("Failed to create the new user");
        return false;
    }
    //...
    return true;
}

. . , , , . - , , . :

  • , ++ ?
  • , - "" ?

: logging " , , ". ( , ), .

: . , , , . (, , .)

+3
7

, -, , , - , . , .

, try log.add - . , - .

void OpenDatabaseConnection()
{
   if (Error) throw MyException("Failed opening database");
}

void CreateUser()
{
    try {
        OpenDatabaseConnection();
        //...... do everything here
    }
    catch(MyException& E) { //only one copy of this code
        E.AddLog(E.getMessage());
        throw;
    }
}
+5

, , . , , , . , , . ?

bool CreateUser(Log& log, UserSecurityContext& u) {
    if (!HasPermissionsFor(u, SecurityRoles::AddUser)) {
        log.Add("Insufficient permissions");
        return false;
    }
    //...
    return true;
}

, (. ), , , , .

+2

, .

, . , . knowldege, . PITA.

, . ( "" , ). - , , catch .

+2

. , . . , , . , . , , ( ), .


. , , .

procedure exceptionTest(...)
{
  try
  {
    call1();
    call2();
    call3();
    call4();
  } 
  catch (...)
  {
    //errorhandling outside the normal control flow
  }
}

:

procedure normalTest(...)
{
   if (!call1())
   {
     //errorHandling1
   } 
   else if (!call2())
   {
     //errorHandling2
   }
   else if ....
   ...
}

, . .

, , . , , . , . , , .

+1

. . log not great errors .

:

int someMethod{
    if(erorr_file_not_found){
        logger.add("File not found");
        return 1;
    }

    if(error_permission){
        logger.add("You have not permissons to write this file");
        return 2;
    }

    return 0;
}

.

( ):

int someMethod{
    int retval=0;
    if(someshit){
        retval=1;
        goto _return;
    }
    //...
    _return:
    switch(retval){
        case 1:logger.add("Situation 1");break;
        case 2:logger.add("Situation 2");break;
        //...
    }
    /*
    close files, sockets, etc.
    */
    return retval;
}

, .

+1

(, ). :

void CreateUser()
{
      OpenDatabaseConnection();
}

, OpenDatabaseConnection().

, .

0

.

  • . , . , , , .

  • . , . , , , :

    void CreateUser() {
        try {
           CDatabaseConnection db = ConnectToDatabase(); 
           InsertIntoDB(db, "INSERT INTO ... "); 
           SetPermission(...);
        } catch(...) {}
    }
    

    InsertIntoDB , , CDatabaseConnection , SetPermission . .

  • , , . . eerrorCONNECTIONLOST, eerrorUSERNAMEINVALID, etc . , (, ). . , , , eerrorCONNECTIONLOST.

0

Source: https://habr.com/ru/post/1723894/


All Articles