mercredi 2 octobre 2019

Exception propagation and context

What is the recommended practice to good context information in an exception? To illustrate here is an simplified example based on experienced.

#include <iostream>
#include <fstream>
#include <boost/filesystem.hpp>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <boost/uuid/string_generator.hpp>
#include <boost/algorithm/string.hpp>

class object
{
public:
  void parse(std::istream& is)
  {
    std::istreambuf_iterator<char> eos;
    std::string buf(std::istreambuf_iterator<char>(is), eos);

    std::vector<std::string> list;
    boost::split(list, buf, boost::is_any_of(","), boost::algorithm::token_compress_on);

    for (auto str : list)
    {
      auto id = boost::uuids::string_generator()(str);
    }
  }
};

void foo()
{
  {
    boost::filesystem::ifstream is("foo.txt");
    object obj;
    obj.parse(is);
  }

  {
    boost::filesystem::ifstream is("bar.txt");
    object obj;
    obj.parse(is);
  }
}

int main()
{
  try
  {
    foo();
  }
  catch (const std::exception& ex)
  {
    std::cout << ex.what() << std::endl;
  }

  return 0;
}

This example reads multiple uuids from two files. If one uuid is poorly formatted an exception is thrown and the output message is "invalid uuid string" which is correct.

In this simple and static example this is probably enough information to figure out the problem but in a more dynamic and complex situation it might not be enough. It would be nice to know which file that contained the invalid uuid and possibly which uuid that failed to parse. Obviously boost::uuid::string_generator cannot provide all that information. One approach would be to catch the original exception early and rethrow with more information but in this case I would need to do that twice to first get "uuid" value and then get "filename".

Appreciate any input on the matter.

Aucun commentaire:

Enregistrer un commentaire